【问题标题】:C# Casting Generic<B> to Generic<A> where B : AC# 将 Generic<B> 转换为 Generic<A> 其中 B : A
【发布时间】:2011-10-06 02:50:04
【问题描述】:

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

public void DoSomething(MyGeneric<MyClassA> obj);

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

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

我知道MyGeneric&lt;MyClassA&gt;MyGeneric&lt;MyClassB&gt; 不属于同一类型,但由于 MyClassB 是 MyClassA 的子类,是否还有办法使这项工作发挥作用?

作为参考,确切的错误信息:

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

【问题讨论】:

    标签: c# generics type-conversion


    【解决方案1】:

    这是泛型中的类型逆变。

    尽管BA 的子类型,
    Generic&lt;B&gt; 不是Generic&lt;A&gt; 的子类型,
    所以你不能将Generic&lt;B&gt; 转换为Generic&lt;A&gt;

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

    你可以将DoSomething()重载为DoSomething(Generic&lt;B&gt;),然后这个方法可以将Generic&lt;B&gt;转换为Generic&lt;A&gt;并调用DoSomething(Generic&lt;A&gt;)

    【讨论】:

    【解决方案2】:

    如果您的泛型类MyGeneric&lt;T&gt; 可以实现interface,它在T 中是协变的,那么您可以执行以下操作:

    1. T中定义一个接口协变:

      public interface IMyGeneric<out T>
      {
          T Foo();
      }
      

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

    2. 让你的类MyGeneric&lt;T&gt;实现IMyGeneric&lt;out T&gt;

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

      IMyGeneric<MyClassB> classBGeneric = new MyGeneric<MyClassB>();
      IMyGeneric<MyClassA> classAGeneric = classBGeneric;
      

      因此,在您的情况下,您可以编写以下内容:

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

    编辑:只需读入您正在使用 .NET 3.5 的 cmets,很遗憾这不适用于您的情况。我会留下答案,以防它对其他人有任何用处。抱歉,我错过了那条重要信息。

    【讨论】:

    • 这仍然是一个很好的答案,它将解决我在 2010 年的问题,我忘了在实际问题中提到我被困在 2008/.NET.3.5 :)
    【解决方案3】:

    大多数 一些泛型类有一个 cast 函数可以为你做这件事。如果它不存在,您可以尝试创建自己的。

    【讨论】:

    • 最多?我知道“大多数通用类都有 Cast 函数”。我知道有一个Cast&lt;T&gt; 扩展方法定义了用于序列,它试图将每个项目转换为序列。您的回答似乎暗示它几乎默认是通用模式的一部分。
    猜你喜欢
    • 2017-01-05
    • 2011-05-30
    • 1970-01-01
    • 2014-03-23
    • 1970-01-01
    • 2021-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多