如何向通用集合中添加项目?

3

假设:

public static void DoStuff<T>(ICollection<T> source)
{
    Customer c = new Customer();
    ....
    source.Add(c);
}

除非 c 的类型是 <T>,否则无法执行操作。

那么我该如何向泛型集合中添加元素呢?


我尝试使用以下代码:

public static void DoStuff(ICollection<Human> source)
{
    Customer c = new Customer();
    ....
    source.Add(c);
}

但我不使用它,因为没有人可以调用DoStuff

ICollection<Customer> c;
DoStuff(c); <---error

因为涉及到协变性的问题,.NET框架无法识别Customer类是由Human类派生而来的。

class Customer : Human {}

你是否真的在处理 source 中包含的元素,还是只想填充集合?是否可能只返回一个新创建的集合? - Clockwork-Muse
我不是在创建一个新列表,而是在修改(添加、修改、删除)传递的列表中的项目。 - Ian Boyd
3个回答

8
只是为了让您知道为什么会出现该错误,因为ICollection<Customer>不能被传递给ICollection<Human>,因为它们不是同一种类型。可以这样想,如果您有一个ICollection<Human>,那么您可以Add(new Deadbeat()),只要Deadbeat派生自Human即可。
其他回答关于泛型的解决方法解决了您的问题(所以他们应该得到答案的认可)。
public static void DoStuff<T>(ICollection<T> source) where T : new()
{
    T c = new T();
    ...
    source.Add(c);
}

但我只是想解释一下为什么会出现这个错误。如果你能将Customer的集合作为Human的集合传递,那么你就可以添加任何类型的人,这将违反原始集合的规定。

因此,即使Customer扩展了Human,这并不意味着ICollection<Customer>扩展了ICollection<Human>,而且ICollection<T>不是协变/逆变的,因为它对inout操作都使用T


7

应该只是:

T t = new T();
....
source.Add(t);

您还需要添加new约束,以确保T具有公共的无参数构造函数:

public static void DoStuff<T>(ICollection<T> source) where T: new()
{
   //...
}

有关如何实现我的需求,您有任何建议吗?我认为我不能使用那种语法来设置我的 T 客户的属性。 - Ian Boyd
@IanBoyd:你想要指定所有客户属性吗?还是只有人类的属性? - James Michael Hare

1
你可能想要这样的东西:
public static void DoStuff<T>(ICollection<T> source)
    where T : new()
{
    T c = new T();
    source.Add(c);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接