私人比私人更私密?(C#)

Fxp*_*per 25 c# field properties

有时您有一个支持属性的私有字段,您只需要通过属性设置器设置字段,以便在字段更改时可以进行其他处理.问题是,从同一类的其他方法中意外绕过属性设置器仍然很容易,并且没有注意到你已经这样做了.有没有办法在C#中解决这个或一般的设计原则来避免它?

Ste*_*ger 41

恕我直言,它没有被使用,因为:

  • 班级必须信任自己
  • 如果你的班级变得那么大,一部分不知道另一部分,那就应该划分.
  • 如果属性背后的逻辑稍微复杂一些,请考虑将其封装在自己的类型中.

  • 听起来不错,但这往往会影响一致,直接的界面,或者需要大量的样板代码,即降低可维护性. (2认同)
  • +1,@ peterchen:你可以创建一个替换类的Facade,从而调用这个被拆分的所有其他类. (2认同)

Luk*_*keH 22

我认为这是一个讨厌的黑客,并尽可能避免它,但......

您可以将支持字段标记为过时,以便编译器在您尝试访问它时将生成警告,然后禁止该属性getter/setter的警告.

那你就需要抑制警告代码是CS0612为平原Obsolete属性和CS0618如果属性有一个自定义消息.

[Obsolete("Please don't touch the backing field!")]
private int _backingField;

public int YourProperty
{
    #pragma warning disable 612, 618
    get { return _backingField; }
    set { _backingField = value; }
    #pragma warning restore 612, 618
}
Run Code Online (Sandbox Code Playgroud)

  • 没有冒犯,但如果在代码审查中发现了这一点,那么编码器就应该被淘汰出局.随着黑客去,它很好:) (10认同)
  • 好吧,我想它确实(有点)回答了这个问题.另外,如果您使用Obsolete("message",true),C#将拒绝在#pragma块之外编译. (4认同)
  • @Binary Worrier:绝对同意.我认为解决这些问题的技术解决方案并不是真正的答案.真正的答案应该是"正确培训您的开发人员,以确保他们不会破解他们不理解的代码". (3认同)
  • 令人印象深刻.我喜欢. (3认同)

Bin*_*ier 20

没有内置的方法来做你想做的事情,但是通过事物的声音,你需要在你的类和那个值之间进行另一层抽象.

创建一个单独的类并将该项放在那里,然后您的外部类包含新类,并且您只能通过其属性访问它.


Jon*_*eet 11

不,没有.我自己也很喜欢这个 - 有点像:

public string Name
{
    private string name; // Only accessible within the property
    get { return name; /* Extra processing here */ }
    set { name = value; /* Extra processing here */ }
}
Run Code Online (Sandbox Code Playgroud)

我想我大约5年前首次在C#新闻组中提出这个问题......我不希望看到它发生过.

在序列化等方面需要考虑各种各样的皱纹,但我仍然认为它会很好.我宁愿先自动实现readonly属性,但......

  • 您只能在构造函数中分配给它.我更喜欢语法`public string Name {get; 私人只读; }`.IT的意图更加冗长但更清晰. (3认同)

Ric*_*ard 7

CAN做到这一点,通过在构造函数(或其他初始化函数)使用在本地封闭.但它需要辅助类接近的更多工作.

class MyClass {
  private Func<Foo> reallyPrivateFieldGetter;
  private Action<Foo> reallyPrivateFieldSetter;
  private Foo ReallyPrivateBackingFieldProperty {
    get { return reallyPrivateFieldGetter(); }
    set { reallyPrivateFieldSetter(value); }
  }

  public MyClass() {
    Foo reallyPrivateField = 0;
    reallyPrivateFieldGetter = () => { return reallyPrivateField; }
    reallyPrivateFieldSetter = v => { reallyPrivateField = v; };
  }
}
Run Code Online (Sandbox Code Playgroud)

我怀疑底层字段类型Foo需要是一个引用类,因此两个闭包是在同一个对象上创建的.


Jos*_*ved 5

C#中没有这样的配置.

但是我会以不同的方式命名私有变量(例如m_something或只是_something),因此在使用它时更容易发现它.


Meh*_*ras 5

您可以将所有私有字段放入嵌套类中,并通过公共属性公开它们.然后在您的类中,您实例化该嵌套类并使用它.这样,如果私有字段属于主类,则无法访问这些字段.

public class A
{
   class FieldsForA
   {
      private int number;
      public int Number
      {
         get
         {
           //TODO: Extra logic.
           return number;
         }
         set
         {
           //TODO: Extra logic.
           number = value;
         }
      }
   } 
   FieldsForA fields = new FieldsForA();

   public int Number
   {
      get{ return fields.Number;}
      set{ fields.Number = value;}
   }       
}
Run Code Online (Sandbox Code Playgroud)

它只是提供了一定程度的阻碍.访问私有支持字段的根本问题仍然存在于嵌套类中.但是,A类中的代码无法访问嵌套类FieldForA的私有字段.它必须通过公共财产.