C# 3.0 C#3.0自动属性,为什么不直接访问该字段?

C# 3.0 C#3.0自动属性,为什么不直接访问该字段?,c#-3.0,properties,C# 3.0,Properties,使用在类的attribute中包含get/set的新方法,如下所示: public string FirstName { get; set; } 为什么不简单地将属性FirstName public放在没有访问器的地方?因为将来,如果更改实现,使用当前接口的代码不会中断 例如,您实现了一个带有公共字段的简单类,并开始在一些外部模块中使用您的类。一个月后,您发现需要在该类中实现延迟加载。然后需要将字段转换为属性。从ciew的外部模块角度来看,它可能看起来是相同的语法,但事

使用在类的attribute中包含get/set的新方法,如下所示:

public string FirstName {
        get; set;
    }

为什么不简单地将属性FirstName public放在没有访问器的地方?

因为将来,如果更改实现,使用当前接口的代码不会中断

例如,您实现了一个带有公共字段的简单类,并开始在一些外部模块中使用您的类。一个月后,您发现需要在该类中实现延迟加载。然后需要将字段转换为属性。从ciew的外部模块角度来看,它可能看起来是相同的语法,但事实并非如此。属性是一组函数,而字段是类实例中的偏移量


通过使用属性,可以有效地降低接口更改的风险。

直接访问类内变量(字段/属性)的两大问题是:

1) 您无法轻松地对字段进行数据绑定


2) 如果从类中公开公共字段,以后就不能将其更改为属性(例如:向setters添加验证逻辑)

这主要是因为它已成为一种常见的编码约定。如果需要,可以很容易地添加自定义处理代码。但你是对的,从技术上讲,这并没有真正的必要。不过,如果您稍后添加自定义处理,这将有助于您不破坏界面。

我想提问者是在问为什么不执行以下操作

public string FirstName { }

既然可以将访问器缩短到上面的长度,为什么还要麻烦访问器呢。我认为答案是,通过要求访问器,阅读代码的人可以清楚地看到它是一个标准的get/set。如果没有它们,您可以看到上面很难发现这是自动实现的。

关键是编译器将属性“under The hood”转换为一个函数对,当您的代码看起来像是在使用该属性时,它实际上在编译到IL时调用函数


假设您将其构建为一个字段,并且在使用该字段的单独程序集中有代码。如果以后实现发生了更改,并且您决定将其作为一个属性来对其余代码隐藏更改,则仍然需要重新编译并重新部署另一个程序集。如果它是一个从开始到结束的属性,那么一切都会正常工作。

对于99%的情况,公开公共字段是可以的

常见的建议是使用字段:“如果从类中公开公共字段,以后就不能将其更改为属性”。我知道我们都希望我们的代码能够经得起未来的考验,但这种想法存在一些问题:

  • 当您更改接口时,类的使用者可能会重新编译

  • 99%的数据成员永远不需要成为非平凡属性。是的。您正在编写大量可能永远不会有用的代码

  • 如果您需要跨版本的二进制兼容性,将数据成员添加到属性中可能是不够的。至少,您应该只公开接口,隐藏所有构造函数,并公开工厂(见下面的代码)


这是一个困难的问题,试图使代码在不确定的未来工作。真的很难


当您遇到错误,需要找出哪些方法在何时修改字段时,您会更加关心。将轻量级的属性访问器放在前面可以避免在出现涉及您所包装的字段的错误时出现大量的心痛。我已经有过好几次这样的经历,但这并不令人愉快,尤其是当它被证明与重新进入有关时


提前完成这项工作并在访问器上粘贴断点比其他方法容易得多。

它保留了对象的封装,并将代码简化为更易于阅读。

当混合使用getter和setter的可访问性时,这种表示法更有用。例如,您可以编写:

public int Foo { get; private set; }
您还可以设置一个内部setter,甚至可以将getter设置为私有,将setter设置为公共


这种表示法避免了仅仅为了处理内部可写/外部可读值这一经典问题而显式编写私有变量的需要。

这会导致“属性或索引器必须至少有一个访问器”错误。它还使编译器{get;}或{set;}或{get;内部集;}等变得显而易见。。。缺少访问器意味着没有访问器。是的,很难生成未来验证代码。因此,您需要采取所有可以采取的预防措施,例如使用属性而不是公共字段。这太简单了,它真的是一个没有头脑的人。”Jay Bazuzi:如果你在一个已列出的列表的中间,代码格式化在WMD中就不起作用。如果在列表和代码之间添加任何内容,它的格式将正确。我只是添加了一个水平规则,因为没有任何有用的东西可以放在两者之间。(Re 2)在访问字段和属性时,它们的语法是否相同?@damagednoob-编译器生成的IL不同,反射代码也不同,因为属性和字段不同。这就是为什么它被认为是一个突破性的变化。如果您可以自己重新编译所有客户机代码,并且不使用反射,那么它可能适合您。我认为第2点非常小,除非您碰巧正在编写类似.NET framework本身的东西。更改库并期望在不向客户端重新编译应用程序的情况下将更新的库推送到客户端,这一点并不常见。如果您处理的是内部类型(首先是大多数类型),则参数首先是一个完全不启动的参数
public int Foo { get; private set; }