我有以下实现接口的类:
public class Category : IHierarchical<Category> {
...
}
然后我有一个名为ProductCategory的继承类型:
public class ProductCategory : Category {
...
}
这是我的IHierachical界面:
public interface IHierarchical<out T> where T : IHierarchical<T> {
T Parent { get; }
IEnumerable<T> Children { get; }
}
最后我有以下扩展方法:
public static string MyExtension<T>(this T item) where T : IHierarchical<T> {
...
}
如果我有类别类型的实例,我可以成功调用我的扩展方法。但是,如果我的实例是ProductCategory类型,我无法调用它的扩展方法,而是我收到错误:
The type 'ProductCategory' cannot be used as type parameter 'T' in the generic
type or method 'IHierarchicalExtensions.MyExtension<T>(T, string)'. There is no
implicit reference conversion from 'ProductCategory' to
'IHierarchical<ProductCategory>'.
我认为通过制作IHierachical协变,它可以解决这个问题。如果有人能告诉我如何做到这一点,我会很感激。感谢
答案 0 :(得分:2)
您的问题是ProductCategory
不符合约束where T : IHierarchical<T>
,因为ProductCategory
实际上是IHierarchical<Category>
,因为它从Category
继承了ProductCategory
。至于如何解决这个问题取决于你想要完成的事情。您可以放弃约束或更改IHierarchical<ProductCategory>
以实施Category
(它仍可继承ProductCategory
)或将Category
投放到T
,或者当您调用扩展方法时,最后将Category
的类型指定为{{1}}。
答案 1 :(得分:2)
我认为你有类似的东西:
Category c = new Category();
ProductCategory pc = new ProductCategory();
c.MyExtension();
pc.MyExtension();//Compiler error!
您的扩展方法允许T
,这意味着您可以传递任何类型,编译时类型pc
为ProductCategory
,因此当您调用MyExtension
时,T是输入ProductCategory
。
约束where T : IHierarchical<T>
怎么样?
它表示ProductCategory
应该是IHierarchical<ProductCategory>
,ProductCategory
显然不是IHierarchical<Category>
。它相当Category
,因此它不会编译。
要解决此问题,您可能需要转发((Category)pc).MyExtension();
。
{{1}}
答案 2 :(得分:2)
T
的推断类型是ProductCategory
,正如编译器错误所示,这不会实现IHierarchical<ProductCategory>
。您可以手动将类型指定为Category
:
var pc = new ProductCategory();
pc.MyExtension<Category>();
答案 3 :(得分:1)
当您将ProductCategory
项目传递给MyExtension
时,T
被推断为ProductCategory
,因此约束为ProductCategory : IHierarchical<ProductCategory>
。它失败,因为ProductCategory
仅实现IHierarchical<Category>
。
协方差意味着可以在期望IHierarchical<ProductCategory>
的地方使用IHierarchical<Category>
个对象。你要做的是相反的。因此,你需要 contravariance ,但这不是解决方案(如果T Parent
是逆变的话,你不能拥有T
属性。)
要成功使用此代码,您可以在通话中指定T
:
ProductCategory pc = ...;
pc.MyExtension<Category>();
这将成功,因为约束变为IHierarchical<Category>
pc
满足。
另一种解决方案是使用泛型接口继承的非泛型接口:
public interface IHierarchical {
...
}
public interface IHierarchical<out T> : IHierarchical where T : IHierarchical<T> {
...
}
public static string MyExtension(this IHierarchical item) {
...
}