使用 => C# 设置 getter

Set a getter using => C#

我可以简化这个吗...

public class Foo : FooBase
{
    public override Valor Nome
    {
        get
        {
            return new Valor
            {
                ValorEntrada = "agência centro"
            };
        }
    }
}

...像这样的事情?

public class Foo : FooBase
{
    public override Valor Nome => Valor.ValorEntrada = "agência centro";
}

Valor 有一个名为 ValorEntrada 的 属性,它接收一个 string

是的。但是您仍然需要带有对象初始化程序的 new 运算符...

public class Foo : FooBase
{
    public override Valor Nome => new Valor { ValorEntrada = "agência centro" };
}

...但是 这是一个糟糕的设计。

  • 假设您的 Valor 类型是 class 而不是 struct,然后在 属性 中返回 new Valor- getter 意味着可能不必要的托管堆对象分配。

    • 虽然分配“便宜”(我个人不会这么说),但 GC 的成本却不是。
    • 在 .NET 中,无论包含对象的状态如何,属性-getters 都应该始终没有副作用并且始终可以安全使用。虽然示例代码中似乎没有任何副作用,但它 确实 打破了调用者对 对象身份.
    • 的期望
    • 例如,这就是 属性 的行为方式,我认为这违反了预期:
      Foo foo = new Foo();
      Valor v1 = foo.Nome;
      Valor v2 = foo.Nome;
      Console.WriteLine( Object.ReferenceEquals( v1, v2 ) ); // "False"
      
  • 您正在使用对象初始化器来设置看起来像 必需的 属性 而不是传递 "agência centro" 字符串通过构造函数参数表明您的 Valor class 是可变的。

    • 鉴于以上几点,这很糟糕。

    • 因为这意味着这会发生:

      Foo foo = new Foo();
      foo.Nome.ValorEntrada = "x";
      Console.WriteLine( foo.Nome.ValorEntrada ); // This prints "agência centro" instead of "x"
      

更好的选择:

更好的解决方案取决于您的 Valor class 究竟代表什么,以及 Nome 属性 的用途。

  • 如果父 class 打算用作工厂,那么您应该使用一种方法,而不是 属性,这样您就不会破坏任何假设或 通过使用 属性:

    强加的隐含合同
    public Valor CreateNewValor() => new Valor { ValorEntrada = "agência centro" };
    
  • 如果 Valor 类型应该是不可变的,那么您应该使用构造函数填充它并将其存储在只读字段(或只读自动 属性)中。使用 static 字段很可能也是合适的,因为拥有相同不可变对象的多个副本毫无意义:

    private static readonly Valor _instance = new Valor( valorEntrada: "agência centro" );
    
    public override Valor Nome => _instance;