【问题标题】:What's the C#-idiomatic way to set a member during construction?在构造期间设置成员的 C# 惯用方式是什么?
【发布时间】:2015-03-26 19:49:08
【问题描述】:

我发现自己写了很多这样的代码:

 new Foo(7, "a");

Foo 的样子:

 class Foo {
      int bar;
      string baz;
      public Foo(int bar, string baz) {
           this.bar = bar;
           this.baz = baz;
      }
 }

受过 C# 培训的程序员会如何处理这个问题?写this.bar = barthis.baz = baz 有效,但感觉很奇怪。

【问题讨论】:

  • 差不多就是这样,有几种不同的方法可以做到这一点,但没有一种方法真的更快。大多数逻辑不会经常进入构造函数,所以它不是那么糟糕
  • bar 和 baz 是类变量。对于属性,您需要定义 setter 和 getter。您可以使用一组;得到;或使用私有变量来存储值。见msdn.microsoft.com/en-us/library/aa287786%28v=vs.71%29.aspx
  • @Tarik 字段适用于私人成员(默认情况下是 barbaz)。如果 barbaz 是公开的,我会同意你的看法。
  • @DStanley 我在这里可能听起来有点迂腐,但我的理解是属性只有在使用访问器定义时才如此,否则它们是类成员。在某些情况下,这种区别会有所不同:例如,当绑定到对象列表时,您可以绑定到属性,但不能绑定到公共成员。
  • @Tarik 啊,我刚刚注意到标题已被编辑.. 这可以解释它。

标签: c# constructor idioms


【解决方案1】:

一种流行的约定是在私有字段名称前加上_,以区别于常见的参数名称,例如

class Foo {
      int _bar;
      string _baz;
      public Foo(int bar, string baz) {
           _bar = bar;
           _baz = baz;
      }
 }

这样就不需要使用this。或者,由于您在问题标题中提到 properties,您可以将这些字段封装在属性中并设置它们:

class Foo {
      int _bar;
      string _baz;
      public Foo(int bar, string baz) {
           Bar = bar;
           Baz = baz;
      }

    public int Bar
    {
        get { return _bar; }
        set { _bar = value; }
    }

    public string Baz
    {
        get { return _baz; }
        set { _baz = value; }
    }
}

由于 C# 具有区分大小写的符号名称,this 仍然没有必要。现在,如果您没有对属性的 get/set 行为做任何比这更复杂的事情,您可以使用 自动属性语法 完全消除字段声明:

class Foo {
    public Foo(int bar, string baz) {
           Bar = bar;
           Baz = baz;
      }

    public int Bar { get; set; }

    public string Baz { get; set; }
}

现在,如果您有共同的要求,即这些属性可以从类外部读取但只能从内部设置,您可以将它们设为只读:

class Foo {
    public Foo(int bar, string baz) {
           Bar = bar;
           Baz = baz;
      }

    public int Bar { get; private set; }

    public string Baz { get; private set; }
}

但是,如果您希望它们真正只在构造函数中设置,则返回使用字段:

class Foo {
      readonly int _bar;
      readonly string _baz;
      public Foo(int bar, string baz) {
           _bar = bar;
           _baz = baz;
      }

    public int Bar
    {
        get { return _bar; }
    }

    public string Baz
    {
        get { return _baz; }
    }
}

【讨论】:

    【解决方案2】:

    您可以使用对象初始化语法:

    var foo = new Foo() { bar = 7, baz = "a" };
    

    它要求您的字段是公开的,并且属性必须有一个设置器。

    编译器会将其翻译成以下代码:

    var temp = new Foo();
    temp.bar = 7;
    temp.baz = "1";
    var foo = temp;
    

    【讨论】:

    • 更新了我的答案以反映这一点。感谢您的评论!
    【解决方案3】:

    我会使用属性而不是字段 - 如果您需要在属性中添加逻辑,以后更容易修改。

    class Foo 
    {
          public int Bar { get; private set; }
          public string Baz { get; private set; }
    
          public Foo()
          {
          }
    
          public Foo(int bar, string baz) 
          {
               Bar = bar;
               Baz = baz;
          }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-06-01
      • 2017-07-28
      • 2023-03-26
      • 1970-01-01
      • 2016-01-27
      • 1970-01-01
      • 2021-06-30
      • 2021-10-10
      相关资源
      最近更新 更多