首页 > 解决方案 > 泛型类型转换异常

问题描述

public interface IRule <T> 
{
     T Execute();
}

public class Rule : IRule<int>
{
    public int Execute()
    {
       return 10;
    }
}

IRule<int> rule = new Rule();
var genericRule = (IRule<object>) rule;
//Exception has occurred: CLR/System.InvalidCastException An exception of ype 'System.InvalidCastException' occurred in test.dll but was not handled in user code: 'Unable to cast object of type 'test.GenericCasting.Rule' to type test.GenericCasting.IRule`1[System.Object]'.'

在业务逻辑中,我需要通过反射加载所有规则对象,并且不知道规则对象中使用的类型。知道如何解决这个问题吗?

标签: c#generics

解决方案


为了在您的示例中执行类型转换,必须满足两个条件:

  1. IRule<T>必须是协变的,也就是说,IRule<out T>
  2. 协方差仅适用于引用类型 as T,也就是说,您不能使用intfor T,但可以使用stringfor 。

一个工作示例:

public interface IRule <out T> 
{
    T Execute();
}

public class Rule : IRule<string> // T must be a reference type
{
    public string Execute()
    {
        return "10";
    }
}

//....

IRule<string> rule = new Rule();
var genericRule = (IRule<object>) rule;

编辑

正如@Servy 正确提到的,我解释了为什么原始代码不起作用,但我没有解释如何解决原始问题。

方法如下:

// define a separate interface for non-typed invocation
public interface IRule
{
    object ExecuteGeneric();
}

public interface IRule<T> : IRule 
{
    T Execute();
}

// every rule implements both typed and non-typed invocation interface
public class Rule : IRule<int>
{
    public int Execute()
    {
        return 10;
    }

    object IRule.ExecuteGeneric()
    {
        return Execute();
    }
}

//.....

IRule<int> rule = new Rule();
IRule genericRule = rule;
// perform non-typed invocation on rules of any T
var genericResult = genericRule.ExecuteGeneric();

推荐阅读