私有类变量的字段和属性哪个更好?

32

私有类变量,哪种更好?

如果你有一个像 int limit 这样的属性,你希望它是:

int Limit {get; set;}

然后在类内部使用它,像这样:

this.Limit

是否有使用或不使用它的原因?也许是出于性能方面的考虑?

我想知道这是否是一个好习惯。

11个回答

31

对于私有成员,我只有在获取和/或设置值会导致其他事件发生时才将其作为属性处理,例如:

private int Limit
{
   get
   {
       EnsureValue();
       return this._limit;
   }
}
否则,字段没问题。如果需要增加它们的可访问性,那么将其变成属性已经是一个大改变了,在这一点上再进行更改不是什么大事。
编辑:正如Scott在评论中提醒我们的那样,属性中的副作用往往会比其他任何事情都更加痛苦。不要违反单一职责原则,并将属性逻辑限制为对值进行一致、逻辑操作的操作,这些操作必须在门口(例如懒加载(如上面的示例)、将内部结构转换为公共有用格式等)上执行。

+1 - 简洁明了,包含代码示例。 - Chris Ballance
1
+1 我读了你的代码,感到很困惑。但是在阅读了你的文章之后,我清楚地理解了代码背后的原因。干得好! - Chuck Conway
5
你应该尽量避免具有副作用的属性。属性会被各种不同的东西所评估,包括调试监视器、本地变量和自动窗口以及快速监视器窗口。因此,具有副作用的属性在调试会话期间可能会导致许多奇怪的行为,并且有时可能会使查找运行时错误变得非常困难。 - Scott Dorman
1
@Scott,确定“副作用”是什么可能会涉及到很多灰色地带。例如,引发PropertyChangedNotification事件怎么办?验证设置到属性中的值怎么办?从数据库中惰性加载值怎么办?对设置到属性中的值进行更改跟踪怎么办?这里可以做很多事情,远远超出了简单设置值的范畴,但又没有经典的“副作用”问题。 - Cylon Cat

13

当可访问性为私有时,自动属性相对于字段唯一的真正优势在于可以设置断点以跟踪变量的访问和更新。如果这对您的情况很重要,那么一定要使用自动属性。否则,鉴于没有实质性的优势,我选择使用最简单的结构,也就是一个字段。


3
你在这里忽略了一件事情,那就是能够在不改变公共接口的情况下进行未来修改的能力。属性(Properties)在公共接口稳定性方面提供了更多的灵活性。 - Cylon Cat

5

我认为使用属性是一个好的实践。如果你需要暴露限制值并使用本地成员,那么需要编写更多的代码;而如果它是一个属性,只需要更改其修饰符即可。

我认为这也更加清晰。


4

考虑到这是一个私有API,它是实现细节 - 你可以在这里做任何想做的事情。然而,即使对于私有类,没有使用属性的很少原因。 JIT会将属性内联,除非存在额外的代码,因此实际上不会影响性能。

我认为更喜欢属性的最大原因是:

  1. API的一致性 - 在公开的API中,您需要属性,因此在私有API中制作它们将使您的编程体验更加一致,从而提高可维护性并减少由此产生的错误。
  2. 更容易将私有类转换为公共类

4

从我的角度来看,使用属性代替变量的原因是:

优点

  • 可以设置断点进行调试,就像Jared提到的那样,
  • 可以引起副作用,比如Rex的EnsureValue()
  • getset可以有不同的访问限制(public get,protected set),
  • 可以在属性编辑器中使用,

缺点

  • 访问速度较慢,需要使用方法调用。
  • 代码臃肿,难以阅读(个人意见)。
  • 更难初始化,比如需要EnsureValue();

并非所有这些都适用于int Limit {get; set;}风格的属性。


2

拥有私有或保护属性并没有什么问题;当底层变量与某些规则或副作用相关联时,这通常非常有用。

属性似乎更适合公共变量的原因是,在公共情况下,它是一种对未来实现变化进行保险的方式,即属性将保持不变,但实现细节会在某种程度上改变(和/或需要某些额外的业务规则)。

就性能而言,这通常是微不足道的,或者对于直接赋值属性来说确实相同。

我个人不喜欢(但经常使用)纯赋值属性,因为它们只会使代码凌乱。我希望C#能够允许“事后重构”。


2
自动属性的优点在于它们可以快速创建类中某个字段的公共访问。现在,与直接将字段暴露给外部世界相比,它们没有任何好处,除了一个重要的好处。
您的类接口是它与外部世界通信的方式。使用自动属性而不是字段允许您在需要设置该属性的值或检查读取时的授权规则或类似情况下,在将来更改类的内部。
事实上,您已经拥有一个属性意味着您可以更改实现而不会破坏公共接口。
因此,如果这只是一个私有字段,则自动属性并不是非常有用,而且您无法像字段一样在声明时初始化公共属性。

2

我通常遵循以下原则:如果只是为了私人使用,请使用字段,因为它更快。

如果你决定它应该在某一天变成公共、受保护的或内部的,重构为属性也不难,而且使用像ReSharper这样的工具大约只需要3秒钟就可以完成... :)


1

属性提供了一些非常好的自动功能(如Json和Xml序列化)。

字段则没有。

属性也可以是接口的一部分。如果您决定以后进行重构...这也可能是需要考虑的事情。


0

属性只是语法糖,C#会将它们编译成get_PropertyNameset_PropertyName,因此性能差异不是一个考虑因素。


2
“get”和“set”用于属性,相当于方法调用,因此属性速度较慢。那么为什么说性能差异不是一个考虑因素呢? - NVRAM
1
因为它们并不是。百万分之一秒的差异除了非常特定类型的情况外,根本没有任何影响。这就像说出于性能原因应该使用for而不是foreach(而这是方法与属性访问之间的更大差异)。 - Matt Briggs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接