【问题标题】:InvalidCastException, may involve genericsInvalidCastException,可能涉及泛型
【发布时间】:2019-05-22 20:44:06
【问题描述】:

我有以下课程:

public interface IA
{
}

public class A : IA
{
}

public interface IB<T> where T : IA
{
    Foo SomeMethod(T someObject);
}

public abstract class BBase<T> : IB<T> where T : IA
{
    // implements SomeMethod();
}

public class BSpecific: BBase<A>
{
    // overrides SomeMethod();
}

这会在运行时引发异常:

var foo = ((IB<IA>)Activator.CreateInstance("BSpecific"));

System.InvalidCastException:无法将 BSpecific 类型的对象转换为 IB'1[IA] 类型

转换为 BBase 会引发相同的异常。

Why I am getting the Unable to cast exception here 是一个非常相似的场景,但推荐的答案(使用逆变/“out T”)不适用于我的情况,因为 SomeMethod() 采用 T 参数。

我不太确定为什么我需要逆变(或者逆变到底是做什么的)。类型和类都被转换为它们实现的接口,所以......?

还有什么我可以做的吗?

(包含转换的代码被包含BSpecific类的项目用作引用,但它本身不知道BSpecific是什么,所以转换是强制性的。)

【问题讨论】:

  • 你试过 IB foo = Activator.CreateInstance("BSpecific") as IB; ? foo 为空吗?也许您应该提供完整的类名,例如:“Namespace.BSpecific”?或者也许你应该尝试使用 Type.GetType("BSpecific") 创建一个类型,然后在激活器中使用这个类型?
  • 你试过了吗?看起来您的 SomeMethod 接受 T 作为函数参数,它与接口的 T 或基类的 T 无关
  • @AdamJachocki 它为空,设置断点告诉我 BSpecific 的实例已正确创建,但随后转换失败。
  • @SKLTFZ 我试过了,编译时错误出现在 SomeMethod() 上,因为 T“必须是逆变有效但协变”。
  • 没有安全的方法来进行这种转换 - BSpecific 实现 IB&lt;A&gt; 所以它的 SomeMethod 方法只接受 A 的实例,而不接受任何 IA 实例。

标签: c# generics casting


【解决方案1】:

BSpecific 继承自 BBase&lt;A&gt; 而不是 BBase&lt;IA&gt;

要么使BSpecific 继承自BBase&lt;IA&gt;,要么将BSpecific 转换为IB&lt;A&gt;,您的代码将编译。

【讨论】:

  • 但是 A 实现了 IA?此外,这两个都需要此代码在编译时知道 BSpecific 或 A 是什么,这是我试图避免的。这被实现抽象类和接口的应用程序用作依赖项,因此 BSpecific 或 A 是什么取决于用例。
  • 你确定不能让BSpecific继承BBase&lt;IA&gt;吗?
猜你喜欢
  • 1970-01-01
  • 2017-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多