作为对另一个问题的响应,我尝试执行以下操作。我不认为我正确地解释了这个问题,但我想知道下面的问题是否有可能(我的尝试失败了),如果不是,原因是:
public class MyBaseClass { }
public class MyClass : MyBaseClass { }
public class B<T> { }
public class A<T> : B<T> { }
static void Main(string[] args)
{
// Does not compile
B<MyBaseClass> myVar = new A<MyClass>();
}我认为这可以使用具有协变量类型参数的泛型接口来实现:
interface IB<out T> { }
public class B<T> : IB<T> { }但我错了,这也没用。
编辑
正如SLaks所指出的,‘接口是协变的,类不是协变的。’(谢谢SLaks)。所以现在我的问题是为什么?这个设计背后的想法是什么(我认为是针对Eric的),是不可能的,不受欢迎的,还是在“也许某一天”的清单上?
发布于 2012-02-21 19:35:11
设计决策背后的思想是什么,不对泛型类类型实现差异?这是不可能的,是不可取的,还是列入了“也许某一天”的名单?
你是好朋友;几周前乔恩·斯基特和比尔·瓦格纳问了我同样的问题。我一直在写一篇博客文章,但简单地说:
微软剑桥研究院的安德鲁·肯尼迪( Andrew )是提出明确答案的合适人选,他最初设计并实现了许多通用和变异逻辑。但是,对于为什么我们决定避免泛型类的差异,我可以进行一个有根据的猜测。
简短的版本是:T的安全协方差要求对T的操作为“只读”。T的逆变要求对T的操作是“只写”。您有一个类C<T>,您希望它在T中是变体,假设‘C’有一个类型为T的字段:您希望该字段只具有可读性还是只能写?因为这是你的选择!
在什么情况下,即使有一个可以写而不读的字段,也是模糊的有用的呢?不是很多。在什么情况下,只有当字段标记为只读时,才能使用可以读取但不能写入的字段?
简而言之,反式泛型类几乎没有用,因为您无法从它们读取任何泛型数据,而且协变类通常只有在类是不可变数据类型时才有用。
我非常喜欢不可变的数据类型,我认为能够在不涉及接口的情况下创建一个协变不可变的堆栈将是一个很好的特性。但是,协变、泛型、持久性、不可变的功能数据结构在C#中还不完全是主流,在将泛型添加到CLR中时,它们当然不是。此外,除了只读字段之外,我们没有其他支持基础设施来表达C#或CLR中“这是一个不可变的数据类型”的概念;如果我们要为不可变类做协变类类型,那么最好做许多支持不可变类的特性,而不仅仅是这个模糊类。
因此,我可以看到这个特性在CLR2.0/ C# 2.0中是如何没有实现的。如果我们今天再次设计它,当功能风格的编程更受欢迎的时候,也许它会。但我们并没有计划在短期内这样做。
我将在接下来的几个月里写一篇博文,给出一个更详细的答案。
发布于 2012-02-21 16:47:28
接口是协变量的,类不是协变量的。
A<MyClass>可以转换为IB<MyBaseClass>。
发布于 2012-02-21 17:01:08
直接类到类的转换不起作用,但是如果您将IB接口用于变量类型,则可以选择。根据此MSDN协方差FAQ博客文章和关于协方差和反方差的MSDN页面,变量类型参数仅限于泛型接口和泛型委托类型。
public class MyBaseClass {}
public class MyClass : MyBaseClass {}
interface IB<out T>{}
public class B<T> : IB<T> {}
public class A<T> : B<T> {}
static void Main(string[] args)
{
IB<MyBaseClass> myVar = new A<MyClass>();
}https://stackoverflow.com/questions/9381507
复制相似问题