C#将Generic <B>转换为Generic <A>,其中B:A

Roy*_* T. 8 c# generics type-conversion

我有两个课程,MyClassA和MyClassB.MyClassB继承自MyClassA.我写了一个带有以下签名的方法

public void DoSomething(MyGeneric<MyClassA> obj);
Run Code Online (Sandbox Code Playgroud)

我还有以下事件处理程序.

public void MyEventHandler(Object source, EventArgs e)
{
   //source is of type MyGeneric<MyClassB>
   DoSomething((MyGeneric<MyClassA>)obj);
}
Run Code Online (Sandbox Code Playgroud)

我知道它MyGeneric<MyClassA>不是同一类型,MyGeneric<MyClassB>但由于MyClassB是MyClassA的子类,还有一种方法可以使它工作吗?

供参考,确切的错误信息:

无法转换类型为'MSUA.GraphViewer.GraphControls.TreeNode 1[MSUA.GraphViewer.GraphControls.MaterialConfigControl]' to type 'MSUA.GraphViewer.GraphControls.TreeNode1 [MSUA.GraphViewer.PopulatableControl]'的对象.

Stu*_*ser 7

这是泛型中的类型逆转.

即使B是子类型A,
Generic<B>也不是子类型Generic<A>,
所以你不能转换Generic<B>Generic<A>.

检查:http://msdn.microsoft.com/en-us/library/dd799517.aspx了解更多详情.

您可以超载DoSomething()DoSomething(Generic<B>),那么这种方法可以转换Generic<B>Generic<A>和调用DoSomething(Generic<A>).


InB*_*een 5

如果您的泛型类MyGeneric<T>可以实现一个interface协变的,T那么您可以执行以下操作:

  1. 在以下位置定义接口协变T:

    public interface IMyGeneric<out T>
    {
        T Foo();
    }
    
    Run Code Online (Sandbox Code Playgroud)

    这意味着泛型类型T只能是输出类型(不能是接口中定义的方法签名的一部分.)

  2. 让你的班级MyGeneric<T>实施IMyGeneric<out T>.

  3. 现在通过interface协变的T,以下代码是有效的:

    IMyGeneric<MyClassB> classBGeneric = new MyGeneric<MyClassB>();
    IMyGeneric<MyClassA> classAGeneric = classBGeneric;
    
    Run Code Online (Sandbox Code Playgroud)

    所以在你的情况下,你可以写下面的内容:

    public void MyEventHandler(object source, EventArgs e)
    {
        DoSomething((IMyGeneric<MyClassA>)source); //IMyGeneric<MyClassB> is implicitly convertible to IMyGeneric<MyClassA>
    }
    
    Run Code Online (Sandbox Code Playgroud)

编辑:只是阅读评论,你正在使用.NET 3.5,所以很遗憾,这不适用于你的情况.我会留下答案,以防它对其他人有用.对不起,我错过了那条重要信息.