【问题标题】:Interface downcasting with generics使用泛型向下转换的接口
【发布时间】:2021-12-28 20:00:53
【问题描述】:

我有以下代码,我想向下转换为具有泛型的接口,但出现运行时异常:无法将“FinalAssociator”类型的对象转换为“IAssociator`1[Common]”类型。

public interface ICommon 
{
    string Name {get;set;}
}
public class Common : ICommon 
{
    public string Name {get;set;}
}
public class FinalCommon : Common {}
public interface IAssociator<T> where T : ICommon
{
    void HandleEvent(T data);
}
public abstract class Associator<T> : IAssociator<T> where T : ICommon
{
    public abstract void HandleAnotherEvent(T data);
    public void HandleEvent(T data)
    {
        HandleAnotherEvent(data);
    }
}
public class FinalAssociator : Associator<FinalCommon>
{
    public override void HandleAnotherEvent(FinalCommon data)
    {
        Console.WriteLine(data.Name);
    }
}
var x = new FinalAssociator();
var y = new FinalCommon { Name = "John" };
var z = (IAssociator<Common>)x;
z.HandleEvent(y);

【问题讨论】:

    标签: c# generics casting polymorphism downcast


    【解决方案1】:

    您不能这样做,因为它可能会由于无效类型而导致运行时错误,这是泛型旨在防止的事情之一。考虑一下如果编译器允许你的代码会发生什么。你有:

    z.HandleEvent(y);
    

    这里的yFinalCommon 的一个实例,不会出现问题。但是,如果您改为传递其他内容,例如:

    z.HandleEvent(new Common());
    

    这将导致您将不是FinalCommon 的实例传递给您的方法,该方法肯定需要FinalCommon 的实例。这将是非法的,编译器会阻止您进入这种情况。

    【讨论】:

      【解决方案2】:

      FinalAssociatior 继承自 Associator&lt;FinalCommon&gt;。它的HandleAnotherEvent 方法需要FinalCommon 类型的参数。

      如果您可以将它的一个实例强制转换为IAssociator&lt;Common&gt;,那么您就可以将Common 类型的参数传递给它,即使该类需要FinalCommon

      var finalAssociator = new FinalAssociator();
      var commonAssociator = (IAssociator<Common>)finalAssociator; // can't do this
      
      // You'd be able to do this because the interface allows it, but it doesn't
      // make sense because the object is a FinalAssociator
      // and it doesn't take this argument.
      commonAssociator.HandleAnotherEvent(new Common()); 
      

      正如所写,编译器无法确定这是无效的,这就是您收到运行时错误的原因。 (Resharper 提供了一个警告,表明这可能在运行时失败。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-05-03
        • 2014-10-09
        • 2023-04-04
        • 1970-01-01
        • 2022-01-21
        • 1970-01-01
        • 2010-12-20
        相关资源
        最近更新 更多