Kev*_*zyk 8 .net c# generics polymorphism
我试图在C#中的泛型类型参数中使用多态.我已经在SO(审查其他几个问题1,2,3,4,5,6),但我仍然不清楚为什么这不工作(或者如果它甚至允许的).
我有以下课程:
public class Base { }
public class Derived<T> : Base { }
public class Foo { }
Run Code Online (Sandbox Code Playgroud)
和我的派生泛型类型的实例:
var derived = new Derived<Foo>();
Run Code Online (Sandbox Code Playgroud)
以下陈述都是正确的:
derived is Object
derived is Base
derived is Derived<Foo>
Run Code Online (Sandbox Code Playgroud)
当我尝试将我的派生类用作另一个泛型类型中的类型参数时,我得到一些意外的行为.鉴于以下惰性实例:
var lazy = new Lazy<Derived<Foo>>();
Run Code Online (Sandbox Code Playgroud)
以下是真实的:
lazy is Lazy<Derived<Foo>>
Run Code Online (Sandbox Code Playgroud)
但是当我预期它们是真的时,这些都是错误的:
lazy is Lazy<Object>
lazy is Lazy<Base>
Run Code Online (Sandbox Code Playgroud)
为什么是这样?它们应该是真的还是我误解了仿制药是如何工作的?
是的,你误解了通用的工作方式.这也是使用Generic类型的最大限制(实际上你应该尽可能地避免使用它们).如果来源于基地继承则是通常不正确的Generic<Derived>
是Generic<Base>
.例外是协方差和逆变.如果你定义你的Generic类,如:
public class Generic<out T> {}
Run Code Online (Sandbox Code Playgroud)
然后 Generic<Derived> is Generic<Base>
如果你定义你的Generic类,如:
public class Generic<in T> {}
Run Code Online (Sandbox Code Playgroud)
然后Generic<Base> is Generic<Derived>
(惊讶,嗯?).
为什么简单演员不起作用?想象一下,我们的Generic类看起来如下:
public class Generic<T>
{
public void Func1(T input);
public T Func2();
}
Run Code Online (Sandbox Code Playgroud)
想象一下,我们有Generic<Derived>
对象,我们正在使用它Generic<Base>
.在这种情况下,Func2完美地工作 - 它返回Derived对象,该对象可以是施法者到Base.但是Func1不起作用 - 我们有一个接受Base对象的函数,但实际对象的Func1只接受Derived对象而不是所有Base对象都是Derived,对吧?
这个例子解释了为什么in和out继承有效.如果我们在泛型类中对类型参数应用约束,我们提交T类型只能从属性或函数返回,但它可能永远不会被接受为参数.在这种情况下,我们的Generic类看起来像这样:
public class Generic<out T>
{
public T Func2();
}
Run Code Online (Sandbox Code Playgroud)
正如我们在之前使用过的Func2,如果我们将使用Generic<Derived>
对象,它将正常工作Generic<Base>
.出于同样的原因:
public class Generic<in T>
{
public void Func1(T input);
}
Run Code Online (Sandbox Code Playgroud)
FUNC1将正常工作,如果对象Generic<Base>
将被用作Generic<Derived>
-在这种情况下,我们会一直传递到FUNC1派生对象作为参数,并Dervied始终是基本定义.
归档时间: |
|
查看次数: |
591 次 |
最近记录: |