首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >泛型类型转换异常

泛型类型转换异常
EN

Stack Overflow用户
提问于 2019-06-29 04:20:07
回答 2查看 139关注 0票数 0
代码语言:javascript
复制
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]'.'

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

EN

回答 2

Stack Overflow用户

发布于 2019-06-29 04:26:58

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

  1. IRule<T>必须是协变的,也就是说,IRule<out T>
  2. Co-variance只适用于引用类型T,也就是说,您不能将int用于T,但可以使用string。例如,

下面是一个工作示例:

代码语言:javascript
复制
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正确提到的,我解释了为什么原始代码不能工作,但我没有解释如何解决原始问题。

下面是如何实现的:

代码语言:javascript
复制
// 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();
票数 2
EN

Stack Overflow用户

发布于 2019-06-29 04:46:32

IRule<object>不是IRule<int>的基本类型,因此强制转换不起作用。

从.NET 4开始,接口可以标记为协变,但只能在特殊情况下使用:泛型参数只能用于输出位置(返回值),并且只能相互转换引用类型。在您的情况下,满足第一个条件,但不满足第二个条件。

对于这种情况,一种可能的解决方案是引入一个非泛型基类型。例如,这就是未知类型参数的List<T>也可以用作IList的原因。

代码语言:javascript
复制
public interface IRule 
{
    object Execute();
}

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

实施:

代码语言:javascript
复制
public class Rule : IRule<int>
{
    // this will be the public implementation (preferred way)
    public int Execute() => 42;

    // the nongeneric implementation if the object is cast to IRule
    object IRule.Execute() => Execute();
}

现在,这将会起作用:

代码语言:javascript
复制
IRule<int> rule = new Rule();
// ...
IRule anyRule = rule;
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56812814

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档