繁体   English   中英

使用 generics 向下转换的接口

[英]Interface downcasting with generics

我有以下代码,我想在其中向下转换为具有泛型的接口,但出现运行时异常:无法将“FinalAssociator”类型的 object 转换为“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);

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

z.HandleEvent(y);

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

z.HandleEvent(new Common());

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

所以首先我会考虑你的例子在这里显示一个通用向上转换的例子,基本上你正在尝试使用一个更派生的通用参数版本,如果你这样做,这将起作用(IAssociator<FinalCommon>)x ,但没有特殊关键字我们无法实现协方差(更多派生的通用参数)。 使用out关键字生成泛型协变可以解决这种情况的问题,但是您不能使用协变泛型 arguments 作为输入,因此您不能使用该方法。 因此,这样的事情实际上是不可能的,请在此处查看有关向上转换通用arguments的答案,以及为何输入不适用于协变通用 arguments 的答案。

FinalAssociatior继承自Associator<FinalCommon> 它的HandleAnotherEvent方法需要一个FinalCommon类型的参数。

如果您可以将它的一个实例强制转换为IAssociator<Common>那么您就可以将Common类型的参数传递给它,即使 class 需要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 提供了一个警告,表明这可能在运行时失败。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM