通用基础,协变

Cap*_*and 0 c# generics list add covariance

我有一个通用的基类,其他泛型类继承它:

public class B<T> {

    private List<T> parent;

    public bool IsInParent() { return parent.Contains(this); }

    public void Attach() { parent.Add(this); }

}
Run Code Online (Sandbox Code Playgroud)

这两个this错误"无法转换B<T>T.我明白这是因为this可能是其他T(协方差)的事实,因此不会进入a List<T>.我理解的很多.

如果我声明T继承自B<T>第一个没有错误,this但Add的错误this仍然存在.

public class B<T> where T : B<T> { ..... ]
Run Code Online (Sandbox Code Playgroud)

现在肯定如果每一个都T继承B<T>,那么每一个B<T>都是一个T,因此应该进入一个List<T>.

我究竟做错了什么?

Eri*_*ert 7

这两个给出了错误"无法转换B<T>T.我明白这是因为this可能是其他的事情T(协方差),因此不会进入List<T>.

我不认为你理解它.

第一种:this属于类型B<T>.想象一下,而不是抽象,B<T>我们使它更具体:

class Comparer<T> // I can compare two things of type T.
{
    ....
Run Code Online (Sandbox Code Playgroud)

this里面Comparer<T>将是类型Comparer<T>.如果你有List<T>,你可以把一个T放入列表.假设TApple. this可以比较两个苹果.该List<T>可包含两个苹果.但是List<T> 不能包含两个苹果比较器,因为那不是它的类型!

其次,你不明白"协方差"这个词是什么意思.我不知道你认为这意味着什么,但我的猜测是你认为"协方差"意味着"赋值兼容性".这通常是人们认为"协方差"意味着它们的含义是错误的.

"作业兼容性"是该类型的值的属性Apple可以进入类型的变量Fruit,因为Apple分配兼容具有给存储Fruit. 这不是协方差.

协方差是通用类型保留赋值兼容性关系的属性.

那就是:一个Apple可以进入一个类型的变量Fruit,因此IEnumerable<Apple>可以进入一个类型的变量IEnumerable<Fruit>.分配兼容性的关系被保留,因为类型通过使它们通用而变化,因此IEnumerable<T>共变体 ; 事物在同一个方向上变化.

如果我声明T继承自B<T>第一个没有错误,但Add this遗骸的错误.

首先:不要这样做.这是一个糟糕的模式.它是C++模式的一种变体,称为"奇怪的重复模板模式".我已经看到它在C#中使用了很多次,而且几乎总是使用错误的.躲开它.它使您的类型变得复杂,难以使用,难以理解,并且它使您认为您对C#不支持的类型有约束.

现在肯定如果每一个都T继承B<T>,那么每一个B<T>都是一个T,因此应该进入一个List<T>.

现在你也许开始明白为什么这种模式太可怕了.它让你相信完全疯狂的虚假事物,因为它太混乱了!

让我们再次让你的句子不那么混乱.我们将代替TAppleB<T>Fruit我们具有:

现在肯定的是,如果每个苹果都是一种水果,那么每个水果都是一个苹果,因此应该进入一碗苹果".

你的结论是,苹果是水果,因此所有的水果都是苹果,所以你可以把香蕉放入一碗苹果中,它仍然是一碗苹果.显然这是荒谬的.

我究竟做错了什么?

您正在构建非常复杂的泛型类型,以至于无法正确理解它们.这意味着使用您的代码的人也无法理解它们.找到一种更简单的方法来解决您的问题.