2012-01-10 104 views
3

在C#中,我们可以创建一个自动实现的属性一样,使用自动实现的属性或由我们自己实现属性

public string MyValue{get;set;} 

然而,我们也可以通过我们自己一样,

private string _myValue; 
public string MyValue 
{ 
    get { retrun _myValue; } 
    set { _myValue = value; } 
} 

创建属性我的问题是我们应该在哪种情况下使用汽车,以及我们应该实施哪种情况?

+1

我可以认为拥有第二种风格的一个原因是,当你想首先初始化_myValue并在ctor中使用默认值时。其他方面,我没有找到有这种风格的其他原因。 – Zenwalker 2012-01-10 02:20:21

+0

StackOverflow不是讨论这些事情的地方。网上有很多资源,你可以从中得到答案。例如:http://msdn.microsoft.com/en-us/library/bb384054.aspx – evasilchenko 2012-01-10 02:20:25

+0

任何时候您需要直接控制存储的值(想法验证),或者需要从内部私下访问该值你的类本身(即使考虑在get或set方法中使用不同的访问修饰符),你需要自己实现这个属性。否则,我倾向于使用自动属性功能来保存几行代码。 – 2012-01-10 02:23:21

回答

5

至少有一个明确的情况,您不应该使用自动实现的属性:两个不同DLL之间的任何类型的二进制序列化。

二进制序列化依赖于私有成员,并且自动实现的属性的私有支持成员不能保证在每个已编译的DLL中相同,因此二进制序列化可能会非常糟糕。

不使用自动实现的属性的另一个原因是,您将失去控制权,是指定支持字段为NonSerialized的能力,但在此情况下,为属性创建支持字段已足够简单。

如果您或您使用的任何产品在成员(即WCF)上执行了反射,则会看到损坏的支持字段名称,而不是您创建的“漂亮”支持字段。

如果您之前提供了对服务的访问权限,或者如果您在接收端反序列化为相同的类结构(即在WCF管道的两端使用相同的类),这可能非常重要。在这种情况下,您不一定能够反序列化,因为您可以保证支持字段名称是相同的,除非您共享相同的DLL而不是源代码。

例如,假设您有一项服务通过WCF将您的一些业务对象公开给您已创建的Silverlight客户端。为了重用您的业务逻辑,您的Silverlight客户端会添加对业务对象源代码的引用。如果您有自动实现的属性,则无法控制后备字段名称。由于WCF序列化成员而不是属性,因此无法确定从WCF服务传输到Silverlight的对象是否会正确反序列化,因为支持字段名称几乎肯定会不匹配。

3

在你给出的例子中,中间语言(IL)大致相同。

然而,当你需要编码干预逻辑而不影响使用它的客户端时,可能会有时间。自动属性对于这种情况非常有用,因为它可以被声明,然后被改为添加一个明确的后台字段。可以在getter/setter中操作后台字段以满足验证和验证要求,而不会影响库或程序集的其他位。最终效果是,您可以在不改变更改的情况下使财产“安全”。

另一个原因宣布支持字段时,例如,在WPF其中一个属性声明...

private string myVar; 
public string MyProperty 
{ 
    [DebuggerStepThrough] 
    get { return myVar; } 
    [DebuggerStepThrough] 
    set 
    { 
     if (value != myVar) 
     { 
      myVar = value; 
      OnPropertyChanged("MyProperty"); 
     } 
    } 
} 

在此声明,一旦支持字段已被分配,二传手然后调用的事件处理程序让外部侦听器知道该属性的值已更改。

因此,作为一般规则,您最初可以使用自动语法声明属性,以便在需要干预时使用getters/setter对它们进行充实。

4

我对这个问题采取的方法很简单但很实用。

始终使用AutoImplemented属性,直到显而易见您需要做一些不同的事情,此时我重构。并且它变得明显。

我喜欢自动属性的可读性,但他们确实有其局限性。使用ReSharper这样的工具使得重构变得非常简单,在某些情况下,R#甚至会为您做出决定。