使用显式接口防止意外修改C#中的属性

时间:2009-11-11 19:41:15

标签: c# methods explicit-interface

我偶然发现了之前没有注意到的C#方法解析功能。也就是说,当我明确地实现支持setter的接口,并且隐式接口仅提供受保护的集合时,编译器在我调用它时明智地遵循受保护的集合。因此,我获得了自动实现属性的大部分便利,但是我可以防止不应该更改它们的客户端意外修改字段。

举个例子,

 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;
    }
}

然后我的模型绑定代码不会意外地设置日期,但我的ORM事件监听器可以检查实现IHaveUpdateDateFields的实体并设置持久化我的实体的日期。

我的问题是:

  1. 我是依赖于定义的行为,还是我保证所有C#编译器都会以这种方式解析方法?我不想发现C#标准说这种方法解决方案是未定义的,然后在我为Mono构建时偶然会出现可怕的堆栈溢出。
  2. 有更好的(理想的terser)方式吗?我可以将一个ModelBinder安全的接口传递给我的控制器,但这似乎不会保存我的代码,我认为它不会提供最小化意外修改属性的透明方法。

1 个答案:

答案 0 :(得分:3)

这是完全明确的;显式接口实现在使用接口时具有优先级,而regular属性则生效(包括在get / set的主体内)。

至于使它更整洁......我能提供的最好的就是重新格式化它以减少它的冗长...

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

(另请注意,this是隐含且冗余的)

顺便说一句 - 安全只是一种便利,而不是保证......外部呼叫者仍然可以使用你的界面,通常(ab)可以使用反射来跳过protected之类的东西 - 甚至只需直接设置字段。