【问题标题】:What are the best practices for Private Member Instantiation/Initialization? [duplicate]私有成员实例化/初始化的最佳实践是什么? [复制]
【发布时间】:2009-05-28 20:41:44
【问题描述】:

可能重复:
C# member variable initialization; best practice?

这样做有什么好处:

public class RemotingEngine
{
    uint m_currentValueId;
    object m_lock;

    public RemotingEngine()
    {
        m_currentValueId = 0;
        m_lock = new object();
    }

对比这个:

public class RemotingEngine
{
    uint m_currentValueId = 0;
    object m_lock = new object();

我一直在避免第二个,只是因为它感觉“脏”。显然打字少了,所以对我很有吸引力。

【问题讨论】:

标签: c# .net


【解决方案1】:

它可以在继承情况下有所作为。对象初始化顺序见此链接:
http://www.csharp411.com/c-object-initialization/

  1. 派生静态字段
  2. 派生的静态构造函数
  3. 派生实例字段
  4. 基础静态字段
  5. 基础静态构造函数
  6. 基本实例字段
  7. 基础实例构造函数
  8. 派生实例构造函数

因此,如果这是一个派生类,则整个基对象都会在派生字段初始化和构造函数运行之间进行初始化。

【讨论】:

    【解决方案2】:

    没有太大的区别,我会保留第一个,因为它更具可读性。通常变量是在类的顶部定义的,我可以去那里检查它们的默认值,而不是寻找构造函数并查看它是否设置了它。就编译器而言,没有区别,除非你有多个构造函数。

    【讨论】:

      【解决方案3】:

      出于这个原因,我总是使用第一个:初始化变量是构造函数的责任。不同的构造函数可能以不同的方式初始化变量。所以,是的,第二种方式你应该觉得很脏=)。

      【讨论】:

        【解决方案4】:

        我更喜欢第二种,在某些情况下,它取决于您的编码标准。但考虑处理顺序:

        目标类字段初始化->基类字段初始化->基类构造函数->目标类构造函数

        如果基类或目标类在创建对象时出现异常,并且字段已预初始化,则它在完成时将具有值,并可能导致一些意外问题。

        另请参阅 Bill Simser Best Practices and Member Initialization in C# 的此博客

        【讨论】:

          【解决方案5】:

          对于 int,您根本不必这样做,内在类型被初始化为 default() - 对于 int 而言,它是 0。

          至于对象,这是我个人喜好的问题。我更喜欢前者。如果有人重写了我的构造函数,我希望他们调用 base() 以在正确的状态下构造它。

          【讨论】:

            【解决方案6】:

            您希望避免在构造函数范围之外进行实例化,因为它显示了意图,特别是如果您要覆盖构造函数,您将拥有更多的灵活性

            【讨论】:

              【解决方案7】:

              就 IL 而言,它们是相同的。

              编译器会这样:

              class Foo
              {
                  int bar = 1;
              }
              

              进入这个:

              class Foo
              {
                  int bar;
              
                  public Foo()
                  {
                      this.bar = 1;
                  }
              }
              

              即使你像这样自己添加构造函数:

              class Foo
              {
                  int bar = 1;
              
                  public Foo(int bar)
                  {
                      this.bar = bar;
                  }
              }
              

              编译器把它变成这样:

              class Foo
              {
                  int bar;
              
                  public Foo(int bar)
                  {
                      this.bar = 1;
                      this.bar = bar;
                  }
              }
              

              【讨论】:

              • 直到添加另一个构造函数
              • @Neil N:请多解释一下——你的说法没有任何意义。
              • 在某些情况下(当您导出时)IL 肯定不一样。
              • 你有具体的例子吗?我看不出有派生类型有什么意义。
              • 如果在基类构造过程中发生异常,派生构造函数不会运行,但字段初始化器会运行。
              【解决方案8】:

              我对此有不同的看法。我认为您应该抽象为属性并将它们设置在构造函数中。使用自动属性基本上可以消除这个问题,因为您无法将它们初始化(除了默认值之外的任何东西)。

              public class RemotingEngine {
                  private uint CurrentValueID { get; set; }
                  private object Lock { get; set; }
              
                  public RemotingEngine()
                  {
                      this.CurrentValueID = 0; // not really necessary...
                      this.Lock = new object();
                  }
              }
              

              【讨论】:

              • 我对公共成员很感兴趣,但对私人成员则不太感兴趣。与私有成员一起工作时,许多支持属性的论点(实现/接口应该分开)并不那么相关..
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2010-09-22
              • 2012-04-20
              • 1970-01-01
              • 2010-12-30
              • 2013-04-09
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多