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对象中使用的类型。你知道怎么解决这个问题吗?
发布于 2019-06-29 04:26:58
为了在您的示例中执行类型转换,必须满足两个条件:
IRule<T>必须是协变的,也就是说,IRule<out T>T,也就是说,您不能将int用于T,但可以使用string。例如,下面是一个工作示例:
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();发布于 2019-06-29 04:46:32
IRule<object>不是IRule<int>的基本类型,因此强制转换不起作用。
从.NET 4开始,接口可以标记为协变,但只能在特殊情况下使用:泛型参数只能用于输出位置(返回值),并且只能相互转换引用类型。在您的情况下,满足第一个条件,但不满足第二个条件。
对于这种情况,一种可能的解决方案是引入一个非泛型基类型。例如,这就是未知类型参数的List<T>也可以用作IList的原因。
public interface IRule
{
object Execute();
}
public interface IRule<T> : IRule
{
new T Execute();
}实施:
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();
}现在,这将会起作用:
IRule<int> rule = new Rule();
// ...
IRule anyRule = rule;https://stackoverflow.com/questions/56812814
复制相似问题