Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么在C#中使用简单属性而不是字段?_C# - Fatal编程技术网

为什么在C#中使用简单属性而不是字段?

为什么在C#中使用简单属性而不是字段?,c#,C#,可能的重复项: 人们似乎教条主义地坚持使用公共属性而不是字段,但为什么它在简单属性的情况下如此重要 怎么样 public int Foo { get; set; } 这和我想象的大不相同 public int Foo; ? 在我脑海中,我能想到这两者之间的一些实际区别: 使用反射访问成员(罕见的、最体面的反射算法将解释差异) 第二个条目允许您将字段用作ref和out参数的有效参数,这似乎是使用字段版本的一个优势 字段在远程处理中不起作用(可能,我从未使用过远程处理,但我想它们不会)?

可能的重复项:

人们似乎教条主义地坚持使用公共属性而不是字段,但为什么它在简单属性的情况下如此重要

怎么样

public int Foo { get; set; }
这和我想象的大不相同

public int Foo;
?

在我脑海中,我能想到这两者之间的一些实际区别:

  • 使用反射访问成员(罕见的、最体面的反射算法将解释差异)
  • 第二个条目允许您将字段用作ref和out参数的有效参数,这似乎是使用字段版本的一个优势
  • 字段在远程处理中不起作用(可能,我从未使用过远程处理,但我想它们不会)?

除了这些非常罕见的情况外,将Foo更改为计算属性之后会导致代码更改0行。

使用属性有两个明显的优点:

  • 如果以后需要额外的逻辑,它允许版本控制。向getter或setter添加逻辑不会破坏现有代码
  • 它允许数据绑定正常工作(大多数数据绑定框架不使用字段)
此外,几乎没有缺点。像这样简单的自动属性由JIT编译器内联,因此没有理由不使用它们

此外,你提到:

除了这些非常罕见的情况之外,将Foo更改为计算属性之后会导致0行代码更改


这不需要更改代码,但它会强制您重新编译所有代码。从字段更改为属性是一种破坏性的API更改,这将要求重新编译引用程序集的任何程序集。通过使其成为自动属性,您只需发布一个新的二进制文件,并保持API兼容性。这就是我上面提到的“版本控制”优势…

主要是因为惯例

一个有力的论据是,如果以后需要将字段更改为属性,则需要重新编译引用您的字段的所有程序集


反省偶尔也会出现,但很少。有些序列化类型是基于属性的。

一个很好的原因是您可以改变get/set可访问性

public int Foo {get; protected set;}

您可以将属性设置为虚拟,并在派生类中重写它们的实现。这是许多将对象封装在生成的代理类中的库中的一个重要因素,例如NHibernate实现延迟加载的方式。这在字段上是不可能的。

属性是一种语言元素,在逻辑上表示类所建模对象的属性。这个级别的汽车模型是一辆汽车;颜色是汽车的特性;因此,颜色是汽车的一种属性


字段是表示类的实现细节的语言元素。您的汽车没有“颜色字段”,因此您的程序对汽车的表示不应暴露名为“颜色”的字段。它可能包含一个私有实现细节,其中属性颜色由一个字段实现,但这是一个私有实现细节,而不是模型的公共可访问部分。

实际上,将变量更改为属性是一个破坏性的更改。当然,它会破坏现有DLL,但不会破坏代码。Mega dupe:,与和有关。我们真的需要另一个吗?@Aaronaught,我同意,我想关闭它。使用属性比使用字段更可取,因为您可以更改get和set块中的语句,而无需更改依赖于属性的类。哇,我实际上没有意识到这一点+1和感谢,尽管构造函数中仅应设置的字段的
只读
修饰符解决了许多情况,但这会有所帮助。而且,现在它是未来,您可以执行
public int Foo{get;}
(由
readonly
字段支持的自动实现的get-only属性)。对于将来的更改,可以将变量设置为属性,而不是字段。但是定义变量或属性之间的差异有好的做法吗?我倾向于同意,您可能不想使用属性的唯一原因是处理
ref
out
要求,尽管您可以轻松地生成一个要使用的临时变量,然后将属性设置为该变量,该变量将很快被释放。使用属性比使用字段更可取,因为您可以更改get和set块中的语句,而无需更改依赖于该属性的类。如果使用set块检查赋值之前的值会使客户机代码的推理变得更加困难:
person.Name=“”;print(person)
可能表示名称已更改,但setter可能会阻止更改。总之,在我看来,使用“集合块”似乎是一种反功能。@MichaWiedenmann这是一个糟糕的编码实践问题。如果一个坏值被拒绝,它应该被拒绝,但有一个例外。我更喜欢这个解释,因为它并不否认属性实际上是语言的一个冗余特性这一事实,如果你从图中去掉这个逻辑语义。唯一剩下的支持者是反射(就像Reed提到的数据绑定)。但这可以通过字段上的注释(属性)来实现。@v.oddou:该语言的几乎每一个功能都是多余的。例如,方法是不必要的;方法只能是用lambdas初始化的委托类型的字段。冗余通常被认为是一件坏事,但事实并非如此;冗余使事情更容易理解。正如我在回答中所指出的,有两个特性、属性和字段,让我们能够巧妙地与读者交流成员在语义上是重要的还是仅仅是一种类型的机制