2012-08-17 15 views
1

结束语在属性力量的所有访问在该领域要经过“吸气”和“二传手”的方法,结构或类领域。这允许为验证添加逻辑,延迟初始化等的可能性。此外,在类字段的情况下,它允许可能具有适用于某些实例但不适用于其他实例的逻辑;如果属性不是虚拟的,它可能难以有效地实现这样的逻辑(例如,一会可能要定义一个静态VerySpecialInstance,并有属性getter说if (this == VerySpecialInstance) GetSpecialProperty(); else GetOrdinaryProperty();),但它可以做。包装是否在价值无关的读写性能正交结构领域服务于一个目的

但是,如果结构的语义(例如System.Drawing.Point)规定特定的读写属性可以写入任何对其类型合法的值,那么除了改变其值之外,写入将没有副作用,它将始终返回最后写入的值(如果有的话),如果没有写入,它将作为其类型的默认值读取;如果使用该类型的代码可能依赖于这些假设,我不清楚使用读写属性而不是字段来保存值可能带来的好处。

,微软使用属性,而不是字段之类的东西Point.X等在历史上造成了混乱,因为MyList[3].X = 4;将被转换为MyList[3].Set_X(4)的事实,并没有看的Set_X这是不可能的定义中来告诉方法是否会实现其在不改变所述结构的任何字段的情况下所需的效果;如今的C#编译器会猜测,这是行不通的,并且将禁止该构造,即使有一些struct哪些类型的属性setter会在实际上工作就好了。如果X是一个领域,而不是一个属性,如果微软曾表示,这两个安全的方式发生变异的结构体要么直接访问字段或传递结构作为ref参数的不同诱变方法(如果它是哪种,结构类型的静态方法,可以访问公共字段),这样的猜测就没有必要了。

由于使用暴露结构领域,而不是读写性能提高了性能和语义清晰,存在什么原因使结构域私下和性能包呢?数据绑定需要属性,但我不认为它适用于结构类型(如果创建了一个结构副本,然后将原始属性设置为一个值并将副本的相应属性设置为另一个值,那么值应该是多少被报告给绑定的对象?)有没有我不知道的结构属性的一些好处?

我个人认为,在很多情况下,“理想”的结构,简直是暴露公共字段列表,并构造方法的参数仅仅是这些领域的初始值,为了。这样的结构将提供最佳性能和可预测的语义(除了字段的类型和名称外,其行为与所有其他此类结构的行为相同)。在没有任何事情可以做任何事情的情况下,除了简单地读写底层字段之外,是否有理由支持读写属性?

回答

1

没有看到使用read/write性能不变的结构任何好处,除了一点,你写的:包裹内的财产的setter和/或吸附剂中的逻辑,以及跨代码库维持一般准则(有利于维护和可读性的观点)。

我亲自当定义一个struct几乎总是使用原料public领域,没有属性,为了简化和我喜欢的类型的易耗

希望(对不可变类型的问题你已经在问题写)这有助于。

+0

我理解类领域的“维护的一般准则”的概念,因为有很多方法人们可能希望将行为(如数据绑定)添加到类的字段特征中。字段可以以属性无法使用的方式使用这一事实可能会被视为包装类字段的论据。我的问题是,鉴于结构和类是不同的,是否有任何合理的理由将这样的指导方针扩展到结构域。 – supercat 2012-08-17 16:18:44

+0

@supercat:正如我所说的,我个人在创建'struct'时使用了字段,所以我个人在'struct'中看不到使用属性的好处。 – Tigran 2012-08-17 16:21:16

+0

感谢您的写作。我想知道其他人是否可以表达相反的观点。 – supercat 2012-08-17 20:32:50

1

Rico Mariani写了good MSDN blog article on this very topic

理由使用公共字段,而不是getter和setter方法包括:

  1. 没有值的字段不能被允许有。
  2. 客户端需要编辑它。
  3. 为了能够写东西,如object.XY = Z.
  4. 为了作出强有力的承诺,价值只是一个价值,没有任何副作用与它相关联(并且不会在未来)。

有些人觉得这很有争议。我怀疑这是因为这个案例很少或根本没有出现在他们编写的软件中,但他们并没有意识到在其他应用领域他们会得到很多。

(这是an answer I provided here副本,但我认为信息是足够有用的在这里重复。)

+0

我认为争议源于恕我直言错误的想法,认为一切都是“对象”是有用的,而不是承认结构类型定义实际上定义了一个堆对象类型(它来自“ValueType”,从而“对象” )和存储位置类型(它不从任何东西派生,但可以转换为堆对象类型或从堆对象类型转换)。如果预计一堆变量与胶带粘在一起表现得像堆物体一样,人们会感到失望和困惑。但是,如果什么是需要的*是一堆变量粘在一起的胶带... – supercat 2015-07-09 15:48:38

+0

...尝试使用一堆变量与胶带粘在一起来模拟一个堆对象,它试图服务于一堆变量的目的与胶带粘在一起,这比使用胶带粘在一起的一堆变量的效率要低* as *一堆变量与胶带粘在一起。 – supercat 2015-07-09 15:50:20

+0

具有讽刺意味的是,我想说数据库场景将是一个结构可能有优势的例子。如果'GetRecord'函数返回一个直接可变的类对象,则可能不清楚该对象的更改是否以及如何应用于数据库。如果它返回一个暴露了RecordContents GetContents(),void UpdateContents(RecordContents)和UpdateResult TryUpdateContents(RecordContents)方法的'LiveRecord'对象,并且'RecordContents'是'struct',那么它会很清楚对... RecordContents结构所做的更改将应用​​于数据库... – supercat 2015-07-10 15:06:31