我的一些类使用一个代表记录器的受保护的只读字段。下面是一些示例代码 -
public class RunJob {
protected readonly ILogger logger;
public RunJob(ILogger logger) { this.logger = logger;}
public virtual void ProcessFiles() {
logger.Log("Start");
...
logger.Log("End");
}
}
经历了很多关于属性和字段的文章/主题,我意识到受保护的字段被认为是坏的,但我想知道我是否会通过将logger作为属性获得任何实际的实际好处。考虑到我上面的用例,下面的3 -
之间是否有任何实际区别protected readonly ILogger logger;
protected ILogger Logger { get; }
或者(protected ILogger Logger {get; private set;}
- 只读子类)#2 backed by a private _logger object
在我的应用程序中,#1运行良好 - 记录器对象在构造函数中初始化一次,然后在整个类(及其子类)中使用,此类及其子类除了调用logger.Log(。 ..)除了这个类及其子类之外没有人关心它是一个字段还是属性。
我已经完成了this thread但很多问题仍未得到答复 -
这里可以应用的一个好处是可以覆盖属性,但在C#中,默认情况下它们是密封的(除非属性与方法不同)。因此,除非开发人员故意将属性设为虚拟,否则此优惠不适用。
使用只读字段是否有任何性能优势?当然,编译器等需要额外工作才能使只读属性有效吗?
我确实在原则上看到了属性对字段的整体好处,即使在我的情况下它只是一行变化,我想知道我是否只是因为它是一个新的很酷的时尚或它是否真的适用于这种情况?
答案 0 :(得分:3)
我可能不会过度思考这个问题 - 在更大的方案中它是not that important。
是的,属性更具有前瞻性和灵活性:
protected ILogger Logger {get; private set;}
内更改,则可以在内部设置其值。Lazy
:private readonly Lazy<ILogger> _logger; protected ILogger Logger {get {return _logger.Value; }}
。protected ILogger Logger {get {return _someParentObject.Logger; }}
。protected ILogger Logger {get {return IsA ? _a : _b; }}
。,但readonly protected
字段实际上并不那么糟糕:
readonly
,不像mutable fields更糟糕。显然,如果它们也是immutable或无国籍(就像你的情况那样),那就更好了。所以:要么让它成为一个属性,所以你不必担心将来的任何变化,或者只是保持原样 - KISS and YAGNI。再一次 - 过分关注它并不是那么重要。
答案 1 :(得分:1)
在这种情况下,我根本不关心性能差异,因为除非你有一个非常好的理由,否则它会很小。您可以阅读过早优化here,例如否则,我不会在这种情况下亲自看到创建受保护属性的重点。属性而不是字段的原因是您可以控制分配,在这种情况下您并不真正需要,因为计划使用无论如何都只是阅读它。虽然理论上孩子们可以覆盖记录器,但可能并不好。但在实践中,我怀疑这可能发生。
关于2对3,据我所知,2只是3的语法糖。我猜它甚至会编译相同,你可以检查一下。
答案 2 :(得分:-1)
protected readonly _logger;
和
protected ILogger Logger { get; }
只能在构造函数中分配。
但是
protected ILogger Logger {get; private set;}
只能用于子类,但可以从同一个类中的任何方法分配;
当你有支持字段时,它是更多的代码行; 我个人更喜欢使用
protected ILogger Logger { get; }
避免将字段暴露给子类,这被认为是一种不好的做法