如何禁止使用字段而不是属性?

ede*_*ane 13 c# properties

我的类中有一个属性,在set访问器中有很多逻辑:

private String text;

public String Text
{
   get { return text; }
   private set
   {
      // some actions with a value
      value = value.Replace('a', 'b');

      text = value;
   }
}
Run Code Online (Sandbox Code Playgroud)

如何防止其他开发人员(甚至是我)更改此类中的字段而不是属性

如果有人写这样的话:

public Test(String text)
{
   this.text = text;
}
Run Code Online (Sandbox Code Playgroud)

它会打破我班级的逻辑!

Mar*_*ell 19

通常,类应该足够小,这不应该是一个问题.由于该字段是private,只有相同类型的代码才能访问该字段.但是,如果您需要强调重要性,您可以:

[Obsolete("Use the Text property, or I break your legs; fair warning")]
private string text;

public string Text
{
#pragma warning disable 0618
    get { return text; }
    private set
    {
        // some actions with a value
        value = value.Replace('a', 'b');

        text = value;
    }
#pragma warning restore 0618
}
Run Code Online (Sandbox Code Playgroud)

这并不能阻止它们,但它可能有助于防止意外使用该场.

  • "或者我打破你的腿(或我的腿)`(因为他也想要阻止自己) (5认同)
  • @edencore旁注:你可能会使用Roslyn实现一个确切的"查找所有非法字段用法并警告它们" - 但问题是,定义"非法字段使用"与"合法字段使用" (2认同)

Bin*_*ier 7

有一个正确的方法来做到这一点.考虑一句古老的格言:"计算机科学中的所有问题都可以通过另一层次的间接解决".

你要做的是创建一个知道如何正确设置文本字段值的类.

class TextSetter
{
    private string text;
    public TextSetter(string text)
    {
        Text = text;
    }
    public string Text
    {
        get{ return text;}
        set{ text = value.Replace('a', 'b');}
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的第一堂课而不是 private string text;你的private TextSetter text; 现在,任何人都不会直接意外地设置值.

如果这是一个常见问题,你甚至可以概括一下

class FieldSetter<T>
{
    private T field;
    private Func<T, T> setter;
    public FieldSetter(Func<T, T> setter, T field)
    {
        this.setter = setter
        Value = field;
    }
    public T Value
    {
        get{ return field;}
        set{ field = setter(value);}
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以随意重命名.


fix*_*gon 5

通过将修改器设置为字段的私有功能,您已经做了尽可能多的事情. 课堂上,你通常应该知道你对它的字段做了什么,逻辑发生在哪里.


Mar*_*ell 5

作为另一种方法,在与Binary Worrier讨论(评论)的基础上,您可以做类似的事情:

internal struct SanitizedText {
    private readonly string value;
    private SanitizedText(string value) {
        this.value = value;
    }
    public static implicit operator string (SanitizedText value) {
        return value.value;
    }
    public static implicit operator SanitizedText(string value) {
        if (value != null) value = value.Replace('a', 'b');
        return new SanitizedText(value);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后简单地说:

private SanitizedText text;
public string Text {
    get { return text; }
    set { text = value; }
}
Run Code Online (Sandbox Code Playgroud)

这会进行所有相同的验证,但不可能滥用:您无法创建SanitizedText绕过验证的值; 同样,它不需要更多的空间(struct内容的大小:1个引用),并且不需要分配.它甚至以null相同的方式默认为字符串.