初始化 C# 自动属性 ​​[重复]

Posted

技术标签:

【中文标题】初始化 C# 自动属性 ​​[重复]【英文标题】:Initializing C# auto-properties [duplicate] 【发布时间】:2008-10-03 22:59:53 【问题描述】:

我习惯于这样写类:

public class foo 
  private string mBar = "bar";
  public string Bar 
    get  return mBar; 
    set  mBar = value; 
  
  //... other methods, no constructor ...

将 Bar 转换为 auto-property 似乎方便简洁,但是如何在不添加构造函数并将初始化放入其中的情况下保留初始化?

public class foo2theRevengeOfFoo 
  //private string mBar = "bar";
  public string Bar  get; set; 
  //... other methods, no constructor ...
  //behavior has changed.

您可以看到,添加构造函数与我应该从自动属性中获得的工作量节省不一致。

这样的事情对我来说更有意义:

public string Bar  get; set;  = "bar";

【问题讨论】:

有什么特别的原因你不想在构造函数中这样做,因为这对我来说似乎很自然。 只是因为我以前不必在构造函数中这样做。因此,如果我必须添加构造函数,这不会为我节省任何精力。 如果它是 STATIC 私有字符串...怎么办?然后你不想在构造函数中初始化,因为每次创建新对象时都会调用它,而这并不是想要的。 ~~~ 问题有点老了,不过回复@StevePitchers和dlamblin,你可以创建一个静态构造函数来初始化你的静态属性一次... @GarryShutler,我找到了一个不想在构造函数中初始化属性的正当理由:如果该属性被标记为virtual 并在派生类中被覆盖,它可能需要不同的初始化逻辑。因为基础构造函数中的初始化代码调用属性设置器而不是直接设置支持字段,所以派生类必须避免使用base() 构造函数以避免触发默认初始化逻辑。看起来像一个滑坡。 【参考方案1】:

更新 - 下面的答案是在 C# 6 出现之前编写的。在 C# 6 中,您可以编写:

public class Foo

    public string Bar  get; set;  = "bar";

你可以写只读的自动实现的属性,这些属性只能在构造函数中写(但也可以给定一个默认的初始值):

public class Foo

    public string Bar  get; 

    public Foo(string bar)
    
        Bar = bar;
    


很遗憾,目前无法做到这一点。您必须在构造函数中设置值。 (使用构造函数链可以帮助避免重复。)

自动实现的属性现在很方便,但肯定会更好。我发现自己并不希望像只读自动实现的属性那样频繁地进行这种初始化,该属性只能在构造函数中设置并由只读字段支持。

这在 C# 5 之前(包括 C# 5)才发生,但正计划在 C# 6 中进行 - 就允许在声明点进行初始化而言,允许只读自动实现要在构造函数主体中初始化的属性。

【讨论】:

这是 VB.NET 团队做对的地方之一 - 在 VB 中,您可以声明您的属性并将其设置在同一行,如下所示:Public Property MyProp As String = "asdf"。不幸的是,您不能像在 C# 中那样声明公共 getter 和私有 setter。不知道为什么两个团队都无法正确实施此功能。 @mattmc3:他们几乎做对了。出于某种原因,它们不允许初始化只读自动属性,即使在语义上它们比初始化的读写属性更有意义。 “Jon Skeet 已经写了一本关于 C# 5.0 的书;目前已被封存。三年后,Anders Hejlsberg 将打开这本书,看看语言设计团队是否做对了。” meta.stackexchange.com/a/9174 @poke: 完成...虽然我不打算像这样更新我的答案所有 :) Resharper 为我建议了这个。我说,当然,将它移到初始化程序然后我找不到它。呵呵。 #programmerproblems【参考方案2】:

你可以通过你的类的构造函数来做到这一点:

public class foo 
  public foo()
    Bar = "bar";
  
  public string Bar get;set;

如果你有另一个构造函数(即一个带参数的构造函数)或一堆构造函数,你总是可以拥有这个(称为构造函数链接):

public class foo 
  private foo()
    Bar = "bar";
    Baz = "baz";
  
  public foo(int something) : this()
    //do specialized initialization here
    Baz = string.Format("0Baz", something);
  
  public string Bar get; set;
  public string Baz get; set;

如果您总是将调用链接到默认构造函数,您可以在那里设置所有默认属性初始化。链接时,链接的构造函数将在调用构造函数之前被调用,这样您的更专业的构造函数将能够设置不同的适用的默认值。

【讨论】:

嗯,我想我真的展示了 3 种方式,不是吗...:P 最后一个例子有点误导,因为内联初始化导致变量在其他构造函数逻辑之前被初始化。您的模式导致在正常构造函数逻辑之后发生初始化(至少在示例 3 中,对于 int something 构造函数)。 DefaultValueAttribute 不设置属性的值。它所做的只是告诉 Visual Studio 的默认值应该是什么,以便在属性窗口中,如果未设置为该值,则会以粗体显示。它不会以任何方式改变值。 +1 James >> MSDN:“DefaultValueAttribute 不会导致成员使用属性值自动初始化。您必须在代码中设置初始值。” 这个答案确实应该更新以删除 DefaultValue 建议,因为它不会像所示那样工作。【参考方案3】:

这将在 C# 6.0 中成为可能:

public int Y  get;  = 2;

【讨论】:

【参考方案4】:

在默认构造函数中(当然还有任何非默认构造函数):

public foo() 
    Bar = "bar";

我相信这与您的原始代码一样性能差,因为无论如何这都是幕后发生的事情。

【讨论】:

如果你有多个不同的构造函数,与只初始化底层字段而不使用自动属性相比,它的工作量更大——我真的看不出在那种情况下你从自动属性中获得了什么收益... 但是有一点不同:立即初始化意味着它甚至在默认构造函数之前就已经初始化了。我最近有一个应用程序,由于一些我不明白的奇怪原因,这实际上很重要。

以上是关于初始化 C# 自动属性 ​​[重复]的主要内容,如果未能解决你的问题,请参考以下文章

[C#详解] 自动属性初始化器扩展方法

C# 6.0 新特性

C#详解属性

C# 3.0新语言特性和改进

C#访问器和初始化[重复]

通过引用传递值类型而不在c#中初始化[重复]