2

Krzysztof 的建议是否适用于构造函数?如果是这样,您如何正确实施它?

我们建议对输出和属性使用 Collection、ReadOnlyCollection 或 KeyedCollection,对输入使用接口 IEnumerable、ICollection、IList。

例如,

public ClassA
{
    private Collection<String> strings;
    public Collection<String> Strings { get { return strings; } }
    public ClassA(IEnumerable<String> strings)
    {
        this.strings = strings; // this does not compile
        this.strings = strings as Collection<String>; // compiles (and usually runs?)
    }
}
4

7 回答 7

5

你应该避免垂头丧气;在您的示例中,我建议您的构造函数参数的类型应该匹配(应该与)您的成员数据的类型(即要么 Collection<String> IEnumerable<String>)。

或者是 Marc 的解决方案,这是不同的:因为 Marc 的解决方案意味着您的成员数据不仅是不同的类型,而且还是不同的实例(即,如果您修改成员数据,那么您正在修改原始集合的副本,而不是编辑原始集合本身;类似地,如果在您制作副本后修改了原始集合,则您的本地副本/成员数据不包括对原始集合的后续更改)。

于 2009-01-09T15:24:21.737 回答
4

您不应该使用该as版本 - 您应该接受并存储可重复的内容,例如IList<T>,或者创建一个新的本地数据集合:

this.strings = new Collection<string>();
foreach(string s in strings) { this.strings.Add(s); }

实际上,我会使用List<T>自己;那么你可以这样做(虽然这不是使用的原因List<T>):

this.strings = new List<string>(strings);
于 2009-01-09T15:24:27.977 回答
1

我相信如果可能的话,应该避免向下转换。如果该类将输入存储为具体类“Collection”(这意味着该类与“Collection”一起使用,那么我认为只接受“Collection”类型的输入而不是接口对应项更自然。

这将向下转换(如果需要)的责任转移回了消费者,如果他确实向下转换,他们应该知道他在做什么。

另一方面,我会说接受输入作为接口比具体类更好,因为它允许更轻松地输入模拟对象的灵活性。但是,这将要求类的内部依赖于接口而不是具体类(因此在示例中,成员变量将是 IEnumerable 而不是 Collection)。

我同意 yapiskan 的观点,即 Marc 的解决方案实际上通过创建输入的副本改变了用法,因此责任发生了变化:

之前:输入在消费者和此类之间始终共享。因此,对输入的更改在消费者和此类之间“共享”

After:调用构造函数后,这个类对输入的理解与消费者分离。

于 2009-01-12T03:23:49.380 回答
0

如果您存储的是 Collection,那么我更喜欢将 ICollection 作为输入。

于 2009-01-09T15:26:32.417 回答
0

这可能都是关于不暴露太多你的实现。理想情况下,如果您正在设计一个公共 API,您应该只公开最低限度的实现。如果您返回一个完整的 List 接口,那么公共 API 的用户将有很多方式以您可能不打算使用的方式弄乱您的类的内部结构。

- - 编辑 - -

于 2009-01-09T15:27:28.467 回答
0

为什么不接受类型参数IEnumerable<String>并将其转换为检索?

public ClassA
{
    private IEnumberable<String> strings;

    public Collection<String> StringCollection {
        get { return (Collection<String>) strings; }
    }

    public ClassA(IEnumerable<String> strings)
    {
        this.strings = strings; 
    }
}
于 2009-01-09T18:20:36.573 回答
0

我会同意佩奇的观点。

我同意您应该将 IEnumerable 作为输入传递(这样您就支持任何可枚举的集合)。

但是你在上面用 StringCollection 属性做的事情对我来说没有意义 - 你正在向下转换,这是行不通的。

-马特

于 2009-01-09T18:36:25.810 回答