【问题标题】:Which is more correct and why?哪个更正确,为什么?
【发布时间】:2011-03-25 16:13:55
【问题描述】:

哪个实现更好还是没有区别?

1.

public class Simple
{
    public IList<string> Entries { get; private set; }

    public Simple()
    {
        Entries = new List<string>();
    }
}

或 2.

public class Simple
{
    private readonly IList<string> entries = new List<string>();
    public IList<string> Entries { get { return entries; } }
}

【问题讨论】:

  • 第一个,因为第二个没有编译;-)
  • 这与我自己的问题非常相似 - stackoverflow.com/questions/5160546/…
  • @Linkgoron:不是这样。我认为他的重点是列表的初始化,而不是是否使用自动属性。
  • 视情况而定。不过,必须在第二个上修复 set 属性。
  • @daniel 我没有说它们完全一样。但是私有集或使用成员的优势非常相关。

标签: c# poco


【解决方案1】:

我假设你的意思是第二个版本:

public class Simple
{
    private readonly IList<string> entries = new List<string>();
    public IList<string> Entries { get { return entries; } }
}

请注意,我已将 entries 变量设为只读。

如果这就是您的意思,因为您不需要在类中的任何位置(可能在构造函数中除外)重新分配变量,那么我认为这比自动属性版本更可取。

它清楚地表明这是意味着是只读的 - 而自动属性只表明它是只读的对外界 .稍后有人(也许是您)可能最终会在类更改自动属性的值,而忘记了最初的设计是将此属性设为只读属性。

(当然,我们实际上并不是在谈论完全不变性,因为任何人都可以在列表中添加或删除条目。)

如果你真的希望能够改变类中的属性值,一定要使用第一个版本。

表达了对只读字段版本的偏好,实际上我发现自己使用自动属性,因为它的读写代码更少。不过每次我都觉得很脏。理想情况下,我想要一种创建只读自动实现属性的方法,该属性只能在构造函数中设置,就像只读字段一样。 (该属性将由一个只读字段支持,并且 setter 调用将直接编译到字段分配中。)不过,我还没有听说过任何计划让这种事情真正发生。

【讨论】:

    【解决方案2】:

    没有真正的实际区别(#2 不会编译,你需要省略 setter)。

    只要在getter中不需要逻辑,不需要直接访问字段,就是风格问题。

    我更喜欢自动属性版本,因为(我觉得)它稍微简单一些,并且在需要时重构为带有支持字段的属性。

    【讨论】:

      【解决方案3】:

      如果您将列表存储在字段中,您可以将该字段标记为readonly,以确保您也不会更改类内的字段。

      public class Simple
      {
          private readonly IList<string> entries = new List<string>();
          public IList<string> Entries { get { return entries; } }
      }
      

      【讨论】:

        【解决方案4】:

        选项 #2 一开始不会编译。

        除此之外,在选项 #2 中,您可以完全省略 set 访问器。例如,这将使PropertyInfo.CanWrite 返回false

        【讨论】:

          【解决方案5】:

          选项 #1 更好,因为在第二个中您也可能错过了 readonly 关键字。

          【讨论】:

            【解决方案6】:

            我更喜欢第二种方法。这样,在您的构造函数运行之前,您就可以使用该列表。这样做的好处是,如果您要添加更多的类构造函数等,您不必担心/记住一遍又一遍地更新列表。

            【讨论】:

            • 如果你把你的构造函数写成链式,你只需要 new 一次,在最细粒度的构造函数中..
            • 是的,假设您记得将它们链接起来。这是一个很小的问题,但你不能告诉我你或任何程序员从未忘记链接。
            【解决方案7】:

            无论是在您公开的 API 还是代码中的语义中,都没有真正的区别(好吧,第一个允许您稍后覆盖 Entries 变量,这可能是您不想要的)。

            大部分区别在于语法,这只是个人喜好问题。

            【讨论】:

              【解决方案8】:

              选择对您来说更易读的那个(或者,如果您正在为具有一致风格的项目编写代码,请保持一致)。

              它们几乎相同(我假设您的意思是在第二个示例中将实例变量声明为私有并省略 setter),但需要注意的一点是自动实现的属性不能标记为 readonly .这是一个非常简洁的功能,但不幸的是,它似乎没有得到应有的使用。

              无论如何,就任何其他类而言,它们是相同的,所以如果你决定改变主意,那只是一个非常微不足道的改变。因此,选择可行的方法,不要太费劲——这不是一个单一风格真正成为“既定规范”的领域。

              就我个人而言,我只在有 readonly 变量时使用第二个,否则使用第一个(打字更少)。嘿 Anders,自动实现的只读属性怎么样?

              编辑

              编辑后的问题有一个更简单的答案:如果字段为readonly,则将其标记为readonly。这样做的唯一方法是第二种方法。

              不区分 readonly 属性并不是什么大罪,但肯定不如区分它们那么清楚(甚至可能有助于防止一些错误)。

              【讨论】:

                【解决方案9】:

                无论如何,第一个编译成这个 IL 的等价物:

                public class Simple{    
                  private IList<string> entries;
                
                  public IList<string> Entries { 
                    get { return entries; }
                  } 
                
                  public Simple() {
                    entries= new List<string>();    
                  }
                }
                

                因此,它们之间的唯一区别是,您的第一个允许实例根据需要更改对不同集合的引用,而另一个则不允许。

                这相当于第二种方法:

                public class Simple{    
                  private readonly IList<string> entries;
                
                  public IList<string> Entries { 
                    get { return entries; }
                  } 
                
                  public Simple() {
                    entries= new List<string>();    
                  }
                }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2020-10-03
                  • 2014-03-20
                  • 1970-01-01
                  • 2011-01-09
                  • 2018-10-07
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-06-07
                  相关资源
                  最近更新 更多