.NET 4.0协方差 [英] .NET 4.0 Covariance

查看:155
本文介绍了.NET 4.0协方差的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在回答另一个<一个href="http://stackoverflow.com/questions/9380756/inheritance-with-c-sharp-generic-while-class-type-is-inherited/9380811#9380811">question我试图做到以下几点。我不认为我跨$ P $正确PTED这个问题,但我不知道下面有可能以某种方式(我尝试都失败了),如果不是为什么不:

 公共类MyBaseClass {}

    公共类MyClass的:MyBaseClass {}

    公共类B&LT; T&GT; {}

    公共类A&LT; T&GT; :B&LT; T&GT; {}

    静态无效的主要(字串[] args)
    {
        //不能编译
        B&LT; MyBaseClass&GT; myVar的=新的A&LT; MyClass的&GT;();
    }
 

我想这可能是做一个使用通用接口与协变类型参数的工作:

 接口IB&LT;出T&GT; {}

    公共类B&LT; T&GT; :IB&LT; T&GT; {}
 

但我错了,那也不行。

修改

由于SLaks指出'接口是协变;类不是。 (感谢SLaks)。所以,现在我的问题是为什么呢?什么是设计(一个用于埃里克利珀我认为)背后的想法是不可能的,不良的或者是一个或许有一天,名单?

解决方案
  

什么是背后的设计决定不实现泛型类的类型变化的思考?它是不可能的,不良的或者是一个或许有一天,名单?

您是在良好的公司;乔恩斯基特和比尔·瓦格纳几个星期前问我同样的问题。我一直在工作了一个博客文章就可以了,但简要地说:

合适的人来问一个明确的答案是安德鲁·肯尼迪在微软剑桥研究院,谁设计和实现许多通用和方差的逻辑最初。不过,我可以大胆的猜测,为什么我们决定避开变化的泛型类。

短的版本为:T的安全协要求对T的操作是只读。的T逆变要求对T的操作是只写。你有一个类 C&LT; T&GT; 你想成为变种T.假设`C具有类型T的一个领域:您希望有一个字段的只可读只写的?因为那些都是你的选择!

在什么情况下是它甚至隐约有用的具有可写,但没有看过现场?不多。在什么情况下是有用的是具有可读取但不能写入场? 只有当该字段为readonly标记

总之,逆变泛型类是几乎从来没有用,因为你不能从中读取任何通用的数据和协类大多只有有用的,如果这个类是不可变的数据类型的。

我是不可变的数据类型的大风扇,我认为这将是一个很大的特点是能够使一个协变不变的堆栈,而不必涉足的接口。但是协变通用持久不变的功能性数据结构是不完全的主流在C#然而,他们当然不时泛型加入到CLR。此外,我们也没有配套的基础设施不是只读领域的前preSS的概念等,这是一个不可变的数据类型在C#或CLR;如果我们做的协变类类型为不可变类,这将是很好做支持一成不变的类的功能的许多的,眼前这个不起眼的。

所以,我可以看到这个功能并没有获得晋级的CLR 2.0 / C#2.0。如果我们今天再设计它,当函数式编程是较为流行,也许会。但是,我们没有计划任何时间做这么快。

我会写在未来几个月博客文章给出了更详细的解答。

In response to another question I have tried to do the following. I don't think I interpreted that question correctly, but I do wonder if the below is possible somehow (my attempts have failed) and if not why not:

    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>();
    }

I thought this might be made to work using a generic interface with a covariant type parameter:

    interface IB<out T>{}

    public class B<T> : IB<T> { }

but I was wrong about that, that does not work either.

EDIT

As SLaks has pointed out 'Interfaces are covariant; classes are not.' (thanks SLaks). So now my question is why? What was the thinking behind the design (one for Eric Lippert I think) is it not possible, undesirable or is it on a 'maybe one day' list?

解决方案

What was the thinking behind the design decision to not implement variance on generic class types? Is it not possible, undesirable or is it on a 'maybe one day' list?

You are in good company; Jon Skeet and Bill Wagner asked me that same question a couple weeks ago. I have been working up a blog post on it, but briefly:

The right person to ask for a definitive answer is Andrew Kennedy at Microsoft Research Cambridge, who designed and implemented much of the generic and variance logic originally. However, I can hazard an educated guess as to why we decided to eschew variance on generic classes.

The short version is: Safe covariance of T requires that operations on T be "read only". Contravariance of T requires that operations on T be "write only". You have a class C<T> which you wish to be variant in T. Suppose `C has a field of type T: would you like to have that field be only readable or only writable? Because those are your choices!

Under what circumstances is it even vaguely useful to have a field that can be written to but not read? Not many. Under what circumstances is it useful to have a field that can be read but not written to? Only if the field is marked readonly.

In short, contravariant generic classes are almost never useful because you can't read any generic data from them, and covariant classes are mostly only useful if the class is an immutable data type.

I am a big fan of immutable data types and I think it would be a great feature to be able to make a covariant immutable stack without having to get an interface involved. But covariant generic persistent immutable functional data structures are not exactly mainstream in C# yet, and they certainly were not when generics were added to the CLR. Moreover, we have no supporting infrastructure other than readonly fields to express the notion "this is an immutable data type" in C# or the CLR; if we were to do covariant class types for immutable classes, it would be nice to do lots of features that support immutable classes, not just this obscure one.

So I can see how this feature did not make the cut in CLR 2.0 / C# 2.0. If we were designing it again today, when functional-style programming is somewhat more popular, maybe it would. But we have no plans to do so any time soon.

I'll write a blog post in the next few months giving a more detailed answer.

这篇关于.NET 4.0协方差的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆