简体   繁体   English

C#泛型继承和协方差

[英]C# generic inheritance and covariance

I'm building a collection library and I'd like to have all the generic collection interfaces require class types and all the collections implementing them to be any type. 我正在构建一个集合库,我希望所有通用集合接口都需要类类型,并且所有实现它们的集合都是任何类型。 So on value types the collection would have two methods, one for the value type and one for boxing it. 所以在值类型上,集合将有两个方法,一个用于值类型,另一个用于装箱。 Is this possible? 这可能吗?

Like this: 像这样:

interface ICollection<ItemType> where ItemType : class
{
    void DoSomething(ItemType item);
}

class Collection<ItemType> : ICollection<ItemType>
{
    void DoSomething(Object item);
    void DoSomething(ItemType item);
}

Barring that what would be the best way to get around it? 除非最好的解决方法是什么? The interfaces being non-generic? 接口是非通用的?

The line: 这条线:

ICollection<Object> s = new Collection<String>();

(comments) would work with out variance; (评论)可以out方差; however, DoSomething(ItemType) would require in variance; 然而, DoSomething(ItemType)将需要in方差; so that type can be neither in nor out : variance does not apply here . 所以类型既不是in也不是out :variance 不适用于此处

The way that is usually handled is by having a generic and non-generic API. 通常处理的方式是使用通用非通用API。 People interested in the specific types can use the generic API; 对特定类型感兴趣的人可以使用通用API; people just interested in "an object" can use the non-generic API. 对“对象”感兴趣的人可以使用非通用API。

For illustration: 例如:

interface ICollection
{
    void DoSomething(object item);
}
interface ICollection<ItemType> : ICollection
{
    void DoSomething(ItemType item);
}

class Collection<ItemType> : ICollection<ItemType>
{
    void ICollection.DoSomething(Object item)
    {
        DoSomething((ItemType)item);
    }
    public void DoSomething(ItemType item)
    {
        //...
    }
}

Then this works: 然后工作:

ICollection s = new Collection<String>();
object o = "abcd";
s.DoSomething(o);

Value types are always boxed as type object . 值类型始终装箱为类型object That would force a collection of any boxed value type to be a Collection<object> , which is not really typesafe (noone prevents you from adding eg a string , then). 这会强制任何盒装值类型的Collection<object>Collection<object> ,它实际上并不是类型安全的(没有人阻止你添加例如string )。 Type safety is meant to be one of the biggest advantages of generic types though. 类型安全性是通用类型的最大优势之一。 So I would suggest dropping the class constraint, if possible. 所以如果可能的话,我建议删除class约束。

BTW: You can still assign these generic interfaces (without class constraint) to their non-generic version: 顺便说一句:您仍然可以将这些通用接口(没有class约束)分配给它们的非通用版本:
IList l = new List<int>();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM