C# 在与值无关的读写属性中包装正交结构字段是否有用

C# 在与值无关的读写属性中包装正交结构字段是否有用,c#,.net,vb.net,struct,C#,.net,Vb.net,Struct,在属性中包装结构或类字段将强制所有对该字段的访问都通过“getter”和“setter”方法。这允许添加用于验证、延迟初始化等的逻辑。此外,在类字段的情况下,允许一个可能具有适用于某些实例但不适用于其他实例的逻辑;如果属性不是虚拟的,可能很难有效地实现此类逻辑(例如,可能必须定义一个静态verysspecialinstance,并让属性getter说,如果(this==verysspecialinstance)GetSpecialProperty();else GetOrdinaryProper

在属性中包装结构或类字段将强制所有对该字段的访问都通过“getter”和“setter”方法。这允许添加用于验证、延迟初始化等的逻辑。此外,在类字段的情况下,允许一个可能具有适用于某些实例但不适用于其他实例的逻辑;如果属性不是虚拟的,可能很难有效地实现此类逻辑(例如,可能必须定义一个静态
verysspecialinstance
,并让属性getter说
,如果(this==verysspecialinstance)GetSpecialProperty();else GetOrdinaryProperty();
),但这是可以做到的

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

Microsoft使用属性而不是字段来表示
Point.X
等内容,这一事实从
MyList[3]开始就在历史上造成了混乱
将被转换为
MyList[3]。Set_X(4)
,如果不查看
Set_X
的定义,就无法判断该方法是否能够在不更改相关结构的任何字段的情况下达到预期效果;今天的C#编译器会猜测它不起作用,并且会禁止这种构造,即使存在一些属性设置器实际上可以正常工作的
struct
类型。如果
X
是一个字段而不是一个属性,并且如果Microsoft说变异结构的两种安全方法是直接访问字段或将结构作为
ref
参数传递给变异方法(如果它是结构类型的静态方法,可以访问公共字段),这样的猜测是没有必要的

考虑到使用公开的结构字段而不是读写属性可以提高性能和语义清晰度,有什么理由使结构字段私有并将其包装到属性中?数据绑定需要属性,但我认为它无论如何都不适用于结构类型(如果一个人复制了一个结构,然后将原始结构的某些属性设置为一个值,将副本的相应属性设置为另一个值,那么应该向绑定对象报告什么值?)结构属性是否有一些我不知道的好处


我个人认为,在许多情况下,“理想”结构只是一个公开的公共字段列表,以及一个构造函数,其参数只是这些字段的初始值。这样的结构将提供最佳性能和可预测的语义(除了字段的类型和名称之外,其行为与所有其他此类结构相同)。如果读写属性除了简单地读写一个底层字段之外,没有其他功能,那么有什么理由支持读写属性吗?

没有看到使用
读/写属性对不可变结构有任何好处,除了您提到的一点:将逻辑包装在属性的setter和/或getter中,并在整个代码库中维护通用指南(从维护和可读性的角度来看)

我个人在定义
struct
时,几乎总是使用原始
public
字段,而不使用属性,以简化和方便使用我的类型(针对您已经在讨论中编写的不可变类型的问题)

希望这能有所帮助。

Rico Mariani写了一篇文章

使用公共字段而不是getter和setter的原因包括:

  • 没有不允许该字段具有的值
  • 希望客户端对其进行编辑
  • 能够写一些东西,比如object.X.Y=Z
  • 做出一个强有力的承诺,即价值只是一个价值,没有与之相关的副作用(将来也不会)
  • 有些人觉得这很有争议。我怀疑这是因为在他们编写的软件中,列出的案例很少或从未出现过,但他们没有意识到在其他应用程序领域中出现过很多


    (这是的副本,但我认为这些信息非常有用,可以在这里重复。)

    我理解类字段的“维护一般准则”概念,因为有很多方法可以将行为(如数据绑定)添加到类的类字段特征中。字段可以以属性无法使用的方式使用,这一事实可能被视为支持或反对包装类字段的参数。我的问题是,鉴于结构和类是不同的,是否有任何逻辑理由将这样的指导原则扩展到结构字段。@supercat:正如我所说,我个人在创建
    struct
    时使用字段,因此我个人在
    struct
    中没有看到使用属性的好处。感谢您的写作。我想知道是否有其他人能表达出相反的观点。@supercat:一般来说不能,因为这是一个普遍接受的准则(我的意思是有一个属性)。但有一次我在看一个来自
    CLR
    团队的家伙的谈话,他说
    属性的开销比较小,但是有。这有点超出了这个问题的主题,但要强调的是,即使是MS,有时违反基本指导原则也是可以的:)使用属性的开销通常很小,但有时可能是巨大的。如果
    biz
    为非读取状态