2

我偶然发现了一个我以前没有注意到的 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. 有没有更好(理想情况下更简洁)的方法来做到这一点?我可以将 ModelBinder 安全接口传递给我的控制器,但这似乎不会为我节省代码,而且我认为它不会提供一种透明的方法来最大限度地减少意外修改属性。
4

1 回答 1

3

这是完美的定义;使用接口时,显式接口实现优先,否则常规属性生效(包括在 get/set 的主体内)。

至于让它更整洁......我能提供的最好的方法是重新格式化它以使其不那么冗长......

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

(另请注意,这this是隐含的和多余的)

顺便说一句 - 安全只是一种方便,而不是保证......外部调用者仍然可以使用您的界面,并且通常可以(ab)使用反射来跳过简单的事情protected- 甚至只是直接设置字段。

于 2009-11-11T19:46:55.750 回答