我理解为什么要使用以下语法来使用只读属性:
private int _MyInt;
public int MyInt
{
get { return _MyInt; }
}
Run Code Online (Sandbox Code Playgroud)
这个例子可能不是最好的例子,因为我认为只读属性真的与readonly
变量一起发光,但这不是重点.我不明白的是为什么使用以下语法使用只写属性:
private int _MyInt;
public int MyInt
{
set { _MyInt = value; }
}
Run Code Online (Sandbox Code Playgroud)
这是各种书籍和教程中描述只读属性的方式.如果设置了变量,你会在概念上阅读一些点,至少在内部的类,但该类中甚至在内部读它,你会被accesssing这样做_MyInt
,我觉得违反了封装的精神,性质试图强制执行.相反,为什么不只是使用具有不同访问修改的属性的全部功能来访问它:
private int _MyInt;
public int MyInt
{
set { _MyInt = value; }
private get { return _MyInt; }
}
Run Code Online (Sandbox Code Playgroud)
当然可以写出来
public int MyInt { set; private get; }
Run Code Online (Sandbox Code Playgroud)
您仍然可以获得封装,但是限制其他类访问,因此它仍然只能写入外部类.
除非有一种情况,你真诚地希望分配给一个变量,但从未实际访问它,在这种情况下,我肯定会对何时出现这种需求感到好奇.
And*_*are 70
我从来没有遇到过只写属性的有效用例.老实说,如果对于只写属性有一个有效的用例,我认为可以肯定地说解决方案的设计很糟糕.
如果您需要"只写"语义,则应使用方法.例如,另一个用户找到了一个用户对象的示例,该用户对象使用只写属性来设置密码.这是一个糟糕的设计:
class User
{
public string Password
{
set { /* password encryption here */ }
}
}
Run Code Online (Sandbox Code Playgroud)
啊.这要好得多:
class User
{
public void SetPassword(string password)
{
/* password encryption here */
}
}
Run Code Online (Sandbox Code Playgroud)
请参阅,读/写属性是一组旨在伪装成字段的方法.它们看起来和感觉就像一块田地.出于这个原因,只读属性是有意义的,因为我们习惯于拥有可以读取但不能更改的字段和变量.但是,没有可写但不可读的相应字段或变量构造.
这就是为什么我认为创建一个使用只写属性的API是不好的做法.它与我认为C#中属性语法的主要目标背道而驰.
编辑:更多哲学......我相信课程有一个功能目的:它们提供了一个容器,用于存储和操作相关数据.以我们的User
课程为例 - 该课程将包含与系统中用户相关的所有信息.我们收集所有这些数据并给它们一个名称:user.通过这种方式,我们使用类来创建抽象.User
是一种抽象,允许我们推理构成用户的所有单个数据(密码,名称,生日等).
现在有很好的抽象,并且有很糟糕的抽象.我认为只写属性是错误的抽象,因为你允许某人输入数据而不是读取数据.你为什么不允许这样做?很可能是因为传入的信息已经以某种方式进行了转换,使得传球者无法理解.
所以这意味着按定义只写属性必须创建调用者看不到的副作用(因为如果他们能看到它们,那么就没有理由让属性只写).用于设置具有副作用的值的C#语言中的最佳构造是方法.
我强烈建议不要使用只写属性,因为您的API的使用者会发现它们令人困惑和令人沮丧.即使您为此语法找到了有效的用例,也无法证明其使用的合理性.
编辑:以下是.Net框架设计指南 - 开发类库 - > 成员设计指南 - > 属性设计的官方建议
不提供仅限设置的属性.
如果无法提供属性getter,请使用方法来实现该功能.方法名称应以Set开头,后跟属性名称...
neo*_*pir 11
只写属性的一个用途是支持setter依赖注入.
假设我上课了:
public class WhizbangService {
public WhizbangProvider Provider { set; private get; }
}
Run Code Online (Sandbox Code Playgroud)
WhizbangProvider不打算被外界访问.我永远不想与之互动service.Provider
,这太复杂了.我需要一个像WhizbangService这样的课程作为门面.然而对于二传手,我可以这样做:
service.Provider = new FireworksShow();
service.Start();
Run Code Online (Sandbox Code Playgroud)
该服务开始烟花汇演.或者你可能更喜欢看水和灯光表演:
service.Stop();
service.Provider = new FountainDisplay(new StringOfLights(), 20, UnitOfTime.Seconds);
service.Start();
Run Code Online (Sandbox Code Playgroud)
等等....
我能看到的一个常见情况是,您是否只希望调用者能够获得您的属性的转换版本.例如:
public int MyInt { set; }
public string MyIntAsString
{
get { return this.MyInt.ToString(); }
}
Run Code Online (Sandbox Code Playgroud)
显然,这不是一个真实的例子,但你得到了图片.
编辑:
在阅读了Thomas的示例用例之后,真正的"转换"类型场景可能是检索只写属性的加密版本:
private string password;
public string ClearPassword { set { this.password = value; }
public string EncryptedPassword
{
get { return Encrypt(password); }
}
Run Code Online (Sandbox Code Playgroud)