在C#中,我们可以创建一个自动实现的属性,如
public string MyValue{get;set;}
但是,我们也可以自己创建一个属性
private string _myValue;
public string MyValue
{
get { retrun _myValue; }
set { _myValue = value; }
}
我的问题是我们应该在哪种情况下使用auto one?我们应该自己实现哪种情况?
答案 0 :(得分:5)
至少有一个明显的例子,你不应该使用自动实现的属性:两个不同的DLL之间的任何类型的二进制序列化。
二进制序列化依赖于私有成员,并且自动实现的属性的私有后备成员不能保证在每个编译的DLL中都是相同的,因此二进制序列化可能会非常糟糕。
不使用自动实现属性的另一个原因是您将无法控制将支持字段指定为NonSerialized的能力,但在这种情况下很容易为属性创建支持字段。
如果您或您使用的任何产品对成员(即WCF)执行反射,那么您将看到错位的支持字段名称,而不是您创建的“漂亮”支持字段。
如果您之前提供了对服务的访问权限,或者您在接收端反序列化为相同的类结构(即在WCF管道的两端使用相同的类),这可能非常重要。在这种情况下,您不一定能够反序列化,因为您可以保证支持字段名称相同,除非您共享相同的DLL而不是源代码。
例如,假设您有一个服务通过WCF将您的某些业务对象公开给您创建的Silverlight客户端。为了重用您的业务逻辑,您的Silverlight客户端会添加对业务对象的源代码的引用。如果您具有自动实现的属性,则无法控制支持字段名称。由于WCF序列化成员而不是属性,因此您无法确定从WCF服务转移到silverlight的对象是否会正确反序列化,因为支持字段名称几乎肯定会不匹配。
答案 1 :(得分:4)
我对这个问题采取的方法很简单但很务实。
始终使用AutoImplemented属性,直到您显然需要做一些不同的事情,此时我重构。它将显而易见。
我喜欢自动属性的可读性,但它们确实有其局限性。使用像ReSharper这样的工具可以使重构变得非常简单,在某些情况下,R#甚至可以为您做出决定。
答案 2 :(得分:3)
在您给出的示例中,中间语言(IL)大致相同。
但是,有时您可能需要对干预逻辑进行编码,而不会影响使用它的客户端。自动属性适用于此类情况,因为它可以声明,然后更改为添加显式支持字段。可以在getter / setter中操作支持字段以满足验证和验证要求,而不会影响库或程序集的其他位。实际效果是,您可以在不中断变更的情况下使财产“安全”。
声明支持字段的另一个原因发生在例如声明属性的WPF中......
private string myVar;
public string MyProperty
{
[DebuggerStepThrough]
get { return myVar; }
[DebuggerStepThrough]
set
{
if (value != myVar)
{
myVar = value;
OnPropertyChanged("MyProperty");
}
}
}
在此声明中,一旦分配了后备字段,setter就会调用事件处理程序,让外部侦听器知道属性的值已更改。
因此,作为一般规则,您最初可以使用自动语法声明属性,并在需要干预时使用getter / setter来充实它们。