代码之家  ›  专栏  ›  技术社区  ›  JasonTrue

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

  •  2
  • JasonTrue  · 技术社区  · 15 年前

    我偶然发现了以前没有注意到的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事件侦听器可以检查实现IHaveUpdateDefields的实体,并在持久化我的实体时设置日期。

    我的问题是:

    1. 我是依赖于已定义的行为,还是我保证所有C编译器都将以这种方式解析方法?我不想发现C标准说这种方法的分辨率是未定义的,然后在我为Mono构建时意外地得到一个可怕的堆栈溢出。
    2. 有没有更好(最好更简洁)的方法来做到这一点?我可以有一个ModelBinder安全接口传递给我的控制器,但这似乎不能节省我的代码,而且我认为它不能提供一种最小化意外修改属性的透明方法。
    1 回复  |  直到 15 年前
        1
  •  3
  •   Jeff Sternal    15 年前

    这是完全定义好的;在使用接口时,显式接口实现优先,而常规属性则以其他方式生效(包括从get/set的主体中)。

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

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

    (还要注意 this 隐式和冗余)

    作为旁白-安全只是一种便利,而不是保证…外部调用方仍然可以使用您的接口,并且通常(ab)使用反射跳过 protected -或者直接设置字段。