【问题标题】:Is there any benefit to a property returning a member of another class instead of setting the property in the constructor?属性返回另一个类的成员而不是在构造函数中设置属性有什么好处?
【发布时间】:2018-01-11 15:53:26
【问题描述】:

我的问题特别涉及使用来自另一个类的某个值初始化属性的好处(或相反),而不是简单地使用属性 get 的值。

例如,是否实现:

public class Foo
{
    public object Bar { get; }

    public Foo()
    {
        Bar = OtherClass.Bar;
    }
}

比这个实现有任何实际优势:

public class Foo
{
    public object Bar { get => OtherClass.Bar; }
}

我之所以问,是因为在我看来,第二种实现更容易阅读,显然更简洁,但我不知道除了行数之外,两者之间是否有任何可衡量的差异。

我能找到的唯一类似问题是C# Is there any benefit to assigning class properties in the class constructor?,这并没有回答我的问题。

【问题讨论】:

  • 在第一个例子中,Bar 的值被初始化一次,然后就永远不会改变。在第二个示例中,每次查询 Bar 时,它都会重新查询 OtherClass.Bar 中的值,因此如果更改了,那么您将返回不同的值。
  • 即使OtherClass.Bar 是只读的,我也有一个重要的区别,为什么我会避免选择第二个选项:您正在创建对OtherClass 的引用,它可以使一个可能并且应该的对象保持活动状态由 GC 收集。
  • @InBetween 在显示的代码中OtherClass 必须是一个类,所以Bar 是一个静态成员。没有任何东西在其中一个而不是另一个中保持活力。
  • @Servy 是的,如果其他类是静态的,我同意。尽管命名约定和显示的代码似乎暗示了它,但这不是事实,这就是为什么我声明它可能保持不应该的东西。这只是他应该考虑的事情。
  • @InBetween 这不是关于命名约定,而是关于范围内没有变量OtherClass 的事实。由于没有名为OtherClass 的变量,它编译的唯一方法是它是一个静态类。

标签: c# constructor properties


【解决方案1】:

存在差异。 get-only 属性 (A) 执行以下操作:

  1. 在调用构造函数时复制值/引用。

  2. 保留该值/参考。

  3. 这意味着 Foo 将在构建时继续引用该属性值的快照。

  4. 这也意味着 Foo 不会让 OtherClass 保持活动状态。

而 lambda 属性正在执行以下 (B):

  1. 调用时取消引用OtherClass,并返回bar的当前值。

  2. 这意味着 OtherClass 将保持活动状态。

  3. 这也意味着可以更改 OtherClass,更改引用它的所有属性值,而无需重新设置它们(或将它们设为只读)。

  4. 最后,也是最重要的一点,它意味着属性的值可以改变(即 Bar 的引用/值)。

就差异而言,当您想要一个值的只读快照时使用 A,当您想要一个可以更改的实时值时使用 B。

【讨论】:

  • (A): Foo 如何不让 OtherClass 保持活力? OtherClass.Bar 是对对象的引用,该引用被复制到 Foo.Bar。在不破坏OtherClass.BarFoo.Bar 引用的对象的情况下,OtherClass 是否可以超出范围?
  • OtherClass 可以被收集,因为它没有被引用,但是对 Bar 的引用会保持活动状态。
【解决方案2】:

两种实现方式不一样:

  • 在调用Foo 的构造函数时,第一个实现“冻结”OtherClass.Bar 的值。如果OtherClass.Bar 稍后更改,Foo.Bar 的用户将看不到它。
  • 第二个实现将在每次获得Foo.Bar 属性时为您提供来自OtherClass.Bar 的当前对象。

一旦您决定了您希望拥有的行为,就只剩下两个选择中的一个。

注意: C# 6 允许您重写第二个示例,如下所示:

public object Bar => OtherClass.Bar;

【讨论】:

  • 只是在第一个实现上要清楚:因为 Bar 是一个对象,它通常是一个引用类型。所以,我仍然会在 this.Bar 中看到来自 OtherClass.Bar 的变化(例如 Bar.someNum)。但是引用不会更新,因此如果 OtherClass.Bar 的基础对象发生更改,则不会在 this.Bar 中反映出来...对吗?
  • @MissingL_tter 对,原始Bar 对象的更改将继续可见;只有用不同的对象替换 Bar 不会对 Foo.Bar 产生任何影响。
猜你喜欢
  • 2011-06-24
  • 2011-01-01
  • 1970-01-01
  • 2014-04-12
  • 2019-05-06
  • 1970-01-01
  • 1970-01-01
  • 2015-06-18
  • 2016-03-29
相关资源
最近更新 更多