你接受接口作为构造函数参数吗?

时间:2009-01-09 15:19:34

标签: .net generics constructor interface robustness

Krzysztof's建议是否适用于构造函数?如果是这样,你如何正确实施?

  

我们建议对输出和属性使用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?)
    }
}

7 个答案:

答案 0 :(得分:5)

你应该避免向下倾斜;在您的示例中,我建议您的构造函数参数的类型应与您的成员数据的类型匹配(应该相同)(即 Collection<String> IEnumerable<String>)。

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

答案 1 :(得分: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);

答案 2 :(得分:1)

我认为应该尽可能避免倾斜。如果类将输入存储为具体类“Collection”(这意味着此类与“Collection”一起使用,那么我认为仅接受“Collection”类型的输入而不是接口对应的输入更自然。< / p>

这将转发(如果需要)的责任转移回了消费者,如果他做了贬低,他应该知道他在做什么。

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

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

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

之后:在调用构造函数之后,此类对输入的理解与使用者分离。

答案 3 :(得分:0)

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

答案 4 :(得分:0)

这可能都是因为没有暴露太多的实现。理想情况下,如果您正在设计公共API,那么您应该只暴露最低限度的实现。如果你返回一个完整的List接口,那么公共API的用户将有很多方法以你可能没有想要的方式搞乱你的类的内部。

---- ----编辑

答案 5 :(得分: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; 
    }
}

答案 6 :(得分:0)

我同意Paige的意见。

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

但是你在上面使用StringCollection属性所做的事情对我来说没有意义 - 你是堕落的,这是行不通的。

-Matt