使用显式接口,以防止在C#中的属性被意外修改 [英] Using Explicit Interfaces to prevent accidental modification of properties in C#

查看:128
本文介绍了使用显式接口,以防止在C#中的属性被意外修改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我偶然在C#方法解析的功能,我之前没有注意到。也就是说,当我明确地实现支持一个二传手,而隐式接口只提供了保护套的接口,编译器明智地推迟到受保护的集时我把它。所以我得到大多数自动实现属性的便利性,但我可以阻止客户谁不应该改变它们的字段意外修改。



作为一个例子,

 虚拟公众的DateTime CreatedOn {搞定;保护套; } 
虚拟公众的DateTime? ModifiedOn {搞定;保护套; }
#地区IHaveUpdateDateFields会员

的DateTime IHaveUpdateDateFields.CreatedOn
{
得到
{
返回this.CreatedOn;
}

{
this.CreatedOn =价值;
}
}

日期时间? IHaveUpdateDateFields.ModifiedOn
{
获得
{
返回this.ModifiedOn;
}

{
this.ModifiedOn =价值;
}
}



然后我的模型绑定代码不小心设置日期,但我的ORM事件侦听器可以检查实现IHaveUpdateDateFields和坚持我的实体时设定日期实体



我的问题是:




  1. 是我依靠定义的行为,还是我保证所有的C#编译器将解决方法,这种方式?我不想发现,C#标准说这种方法解决的是不确定的,当我建立单声道,例如然后小心弄一个可怕的堆栈溢出。

  2. 有没有更好的(理想情况下更简洁)的方式来做到这一点?我可以有一个ModelBinder的安全界面,我传递给我的控制器,但似乎并不像它会救我的代码,我不认为这将减少提供物业意外​​修改为透明的方法。


解决方案

这是非常明确的;显式接口实现使用界面时优先,和普通的属性生效,否则(包括从获取/设置的本体之内)。



至于使其整洁......我能提供的最好是重新格式化它,使之更简洁...

 日期时间IHaveUpdateDateFields.CreatedOn 
{
{返回CreatedOn; }
集合{CreatedOn =价值; }
}



(另请注意,这个是隐含的,冗余)



顺便说一句 - 安全只是一个方便,不保证...外部呼叫者仍然可以使用自己的接口,以及通常可以(AB)使用反射来跳过去的单纯之类的东西保护 - 甚至只是直接设置域


I stumbled on a feature of C# method resolution that I didn't notice before. Namely, when I explicitly implement an interface that supports a setter, and the implicit interface only offers a protected set, the compiler sensibly defers to the protected set when I call it. So I get most of the convenience of auto-implemented properties, but I can prevent accidental modification of fields by clients who shouldn't be changing them.

As an example,

 virtual public DateTime CreatedOn { get; protected set; }
 virtual public DateTime? ModifiedOn { get; protected set; }
 #region IHaveUpdateDateFields Members

 DateTime IHaveUpdateDateFields.CreatedOn
 {
    get
    {
        return this.CreatedOn;
    }
    set
    {
        this.CreatedOn = value;
    }
}

DateTime? IHaveUpdateDateFields.ModifiedOn
{
    get
    {
        return this.ModifiedOn;
    }
    set
    {
        this.ModifiedOn = value;
    }
}

Then my model binding code doesn't accidentally set the date, but my ORM event listener can check for entities that implement IHaveUpdateDateFields and set the date when persisting my entity.

My questions are:

  1. Am I relying on defined behavior, or am I guaranteed that all C# compilers will resolve methods this way? I don't want to discover that the C# standard says this kind of method resolution is undefined and then accidentally get a horrifying stack overflow when I build for Mono, for example.
  2. Is there a nicer (ideally terser) way to do this? I could have a ModelBinder-safe interface that I pass to my controller, but that doesn't seem like it would save me code and I don't think it would provide as transparent an approach of minimizing accidental modification of properties.

解决方案

That is perfectly well defined; the explicit interface implementations take priority when using the interface, and the regular property takes effect otherwise (including from within the body of the get/set).

As for making it tidier... the best I can offer is to reformat it to make it less verbose...

DateTime IHaveUpdateDateFields.CreatedOn
{
    get { return CreatedOn; }
    set { CreatedOn = value; }
}

(note also that the this is implicit and redundant)

As an aside - the safety is only a convenience, not a guarantee... external callers can still use your interface, and can usually (ab)use reflection to jump past mere things like protected - or even just set the fields directly.

这篇关于使用显式接口,以防止在C#中的属性被意外修改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆