集合类型的属性

时间:2010-02-19 09:53:51

标签: c# collections properties ienumerable

当属性有一些类似

的集合类型时
public IList<MyItemClass> MyList{ get; }

恕我直言,最好返回空集合而不是空值。
有很多方法可以实现这样的功能。

public IList<MyItemClass> MyList{ get; private set; }
public MyClass(){
    MyList = new List<MyItemClass>();
}

这种方法允许减少类字段的数量,但是你需要在每个构造函数中放置代码。

private List<MyItemClass> _myList = new List<MyItemClass>();
public IList<MyItemClass> MyList{ get{ return _myList; } }

这是标准方式。但是当有人在你的代码中写一些东西时,他可以使用私有字段而不是属性,当你重构动作时你可以得到一些错误。

private List<MyItemClass> _myList;
public IList<MyItemClass> MyList{ get{ return _myList??(_myList = new List<MyItemClass>()); } }

这是延迟加载的前一种方式的变体。

您更喜欢将哪些内容作为收藏的默认值返回?如果这是空集合,你如何实现它?

5 个答案:

答案 0 :(得分:2)

来自.NET Design Guidelines

  

为所有属性提供合理的默认值,确保默认值不会导致安全漏洞或设计效率极低。

扩展这一原则并将其与Principle of Least Surprise相结合,应该非常明确地表明你应该总是返回一个空集合而不是null。

为什么当你能提供合理,直观的默认值时,为你的来电者检查null的负担呢?

封装的重点是在单一地点中完成工作。它可能使特定的类实现更复杂,但它使得使用它的API更简单。

在大多数情况下,我将集合实现为包含类型中的不变量:

public class MyClass
{
    private readonly List<Foo> foos;

    public class MyClass()
    {
        this.foos = new List<Foo>();
    }
}

请注意readonly关键字的使用,该关键字确保一旦设置,列表永远不会被替换或删除(但它仍然可以重置)。这可以保护列表作为类的不变量,这使我无需在其余代码中编写空值检查。

延迟加载也是一种有效的编码习惯,但我只在明确需要时使用它。

答案 1 :(得分:1)

返回null确实不理想。替代品;这取决于用途。 IMO,这个版本(从主帖复制)是最简单的,但我们需要做的一切:

private List<MyItemClass> _myList = new List<MyItemClass>();
public IList<MyItemClass> MyList { get { return _myList; } }

并且作为一个优势,它可以与XmlSerializer一起使用,因为private set 的任何内容都不会工作(一个错误;它会看到设置者但是没有注意到它不能使用它。)

懒惰的方法通常是过度使用IMO,因为在大多数有趣的情况下,无论如何你都要填充列表。

答案 2 :(得分:1)

我通常使用变量来初始化构造函数中的列表。这可能会使构造函数更“膨胀”,但构造函数的责任是构造对象。设置好的默认值是恕我直言,完全在其职责范围内。此外,作为奖励,您不必担心私有字段会使代码看起来更清晰。

当然,重构确实会让变得更难,但并不显着。不要忘记你可以链接你的构造函数(无论如何大多数情况下),所以即使你有几个构造函数,你也应该只需要编写一次初始化代码。

不要忘记记录默认值是空集合。并且将收集字段设置为只读是好的做法,除非您有充分的理由稍后重置它。

答案 3 :(得分:0)

选项2(标准方式)并通过确保您的单元测试检查在您预期的时间返回空列表来避免重构问题。

答案 4 :(得分:0)

我更喜欢第二种变体,因为它更明显并且减少了构造函数的大小。 但通常是只读这个字段:

private readonly List<MyItemClass> _myList = new List<MyItemClass>();