为什么要使用带有接口约束的泛型?
Why to use generic with interface constraint?
在创建通用接口时,我可以定义通用参数应从特定接口 (IBase) 继承的约束。
interface IGeneric<T> where T : IBase
{
List<T> property{get; set;}
}
这个有什么用吗?因为我可以将其替换为以下界面,它具有相同的目的并且更简单。
interface IGeneric
{
List<IBase> property{get; set;}
}
在我看来,在这种情况下我们根本不需要泛型,因为我们已经知道 T 将是 IBase。 IBase 属性 已经可以容纳所有派生类型。那么具有特定接口约束的泛型有什么用呢?
这两个接口是很不一样的,因为List<T>
和List<IBase>
是很不一样的。假设有一个 class A
实现了 IBase
。首先,这不编译:
IGeneric noTypeParameter = ...
noTypeParameter.property = new List<A>();
但是这样做:
IGeneric<A> hasTypeParameter = ...
noTypeParameter.property = new List<A>();
这是因为 List
在 T
上不是协变的。事实上它是不变的。另见:Convert List<DerivedClass> to List<BaseClass>
如果你使用 IEnumerable<T>
和 IEnumerable<IBase>
,那么上面的两个代码片段都可以编译,但是两个 IGeneric
接口仍然不同,因为:
IGeneric noTypeParameter = ...
IEnumerable<A> enumerable = noTypeParameter.property; // does not compile
IGeneric<A> hasTypeParameter = ...
IEnumerable<A> enumerable = noTypeParameter.property; //does compile
所以基本上,使用通用参数,您可以将特定类型的 List
传递给接口,并获取特定类型的 List
。但是,您不能“存储任何 IBase
实现的 property
”。如果没有类型参数,您可以存储任何 IBase
实现的 property
,但您无法获取特定类型 of/into IGeneric
.
在创建通用接口时,我可以定义通用参数应从特定接口 (IBase) 继承的约束。
interface IGeneric<T> where T : IBase
{
List<T> property{get; set;}
}
这个有什么用吗?因为我可以将其替换为以下界面,它具有相同的目的并且更简单。
interface IGeneric
{
List<IBase> property{get; set;}
}
在我看来,在这种情况下我们根本不需要泛型,因为我们已经知道 T 将是 IBase。 IBase 属性 已经可以容纳所有派生类型。那么具有特定接口约束的泛型有什么用呢?
这两个接口是很不一样的,因为List<T>
和List<IBase>
是很不一样的。假设有一个 class A
实现了 IBase
。首先,这不编译:
IGeneric noTypeParameter = ...
noTypeParameter.property = new List<A>();
但是这样做:
IGeneric<A> hasTypeParameter = ...
noTypeParameter.property = new List<A>();
这是因为 List
在 T
上不是协变的。事实上它是不变的。另见:Convert List<DerivedClass> to List<BaseClass>
如果你使用 IEnumerable<T>
和 IEnumerable<IBase>
,那么上面的两个代码片段都可以编译,但是两个 IGeneric
接口仍然不同,因为:
IGeneric noTypeParameter = ...
IEnumerable<A> enumerable = noTypeParameter.property; // does not compile
IGeneric<A> hasTypeParameter = ...
IEnumerable<A> enumerable = noTypeParameter.property; //does compile
所以基本上,使用通用参数,您可以将特定类型的 List
传递给接口,并获取特定类型的 List
。但是,您不能“存储任何 IBase
实现的 property
”。如果没有类型参数,您可以存储任何 IBase
实现的 property
,但您无法获取特定类型 of/into IGeneric
.