使用泛型进行接口向下转型

Interface downcasting with generics

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

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

z.HandleEvent(y);

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

z.HandleEvent(new Common());

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

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 提供了一个警告,表明这可能会在运行时失败。)