我有一个接口IGenericOrder
,如下所示:
using System;
using System.Linq.Expressions;
namespace MyNamespace
{
interface IGenericOrder<T> where T : new()
{
Func<T, int> GetStatement(string name);
}
public class GenericOrder<T> : IGenericOrder<T> where T : new()
{
public Func<T, int> GetStatement(string name)
{
return (T) => 4;
}
}
}
现在,当我创建该类的实例并将其强制转换回IGenericOrder<object>
var sorter = (IGenericOrder<object>) new GenericOrder<Foo>();
我得到例外:
InvalidCastException:类型
GenericOrder<Foo>
的实例无法强制转换为IGenericOrder<object>
这似乎很清楚,因为接口IGenericOrder
不是协变的。但是,如果我使接口协变(interface IGenericOrder<out T>
),我得到编译器错误:
无效方差:类型参数&#39; T&#39;必须在
IGenericOrder<T>.GetStatement(string)
上违反有效。 &#39; T&#39;是协变的。
当我从here读取时,协方差只能在
时使用[泛型类型参数]仅用作方法返回类型,不用作形式方法参数的类型。
这是否意味着我不能对他们自己返回通用实例的方法使用共同/逆变?
我正在使用.Net 4.5
答案 0 :(得分:2)
要了解正在进行的操作,请查看Func<T,TResult>
委托的定义:
public delegate TResult Func<in T, out TResult>(
T arg
)
如您所见,其第一个类型参数T
是in
参数。因此,您不能将out
参数用作Func
的第一个类型参数。第二个类型参数TResult
为out
,因此使用T
作为TResult
可行:
interface IGenericOrder<out T> where T : new() {
Func<int,T> GetStatement(string name);
}
public class GenericOrder<T> : IGenericOrder<T> where T : new() {
public Func<int,T> GetStatement(string name) {
return (x) => default(T);
}
}
答案 1 :(得分:1)
您使用T
作为Func
的第一个类型参数,因此唯一有效的模式是 contravariance ,因为T
表示函数的类型参数。你试图用你的演员实现的是不安全的:你说的是“这是一个以Foo
为参数的函数。请将此视为一个以object
为参数的函数。”如果你有一个Func<int, T>
,你可以使用协方差,因为返回Foo
的函数也可以被视为一个返回object
的函数。