转换为泛型方法不支持的基类型

cast to base-type not supported for generic method

我有一个接口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;
        }    
    }
}

现在,当我创建 class 的实例并将其转换回 IGenericOrder<object>

var sorter = (IGenericOrder<object>) new GenericOrder<Foo>();

我得到异常:

InvalidCastException: The instance of type GenericOrder<Foo> cannot be cast to IGenericOrder<object>

这似乎很清楚,因为接口 IGenericOrder 不是协变的。但是,如果我使接口协变 (interface IGenericOrder<out T>),我会得到一个编译器错误:

Invalid variance: The type parameter 'T' must be contravariantly valid on IGenericOrder<T>.GetStatement(string). 'T' is covariant.

正如我从 here 中读到的那样,协方差只能在

时使用

[the generic type parameter] is used only as a method return type and is not used as a type of formal method parameters.

这是否意味着我不能将 co-/contravariance 用于自身具有 return 个通用实例的方法?

我正在使用 .Net 4.5

您正在使用 T 作为 Func 的第一个类型参数,因此唯一有效的模式是 contravariance 因为 T 表示函数参数的类型。你试图用你的演员实现的是不安全的:你说 "Here's a function which takes a Foo as a parameter. Please treat this as a function which takes any object as a parameter." 如果你有一个 Func<int, T>,你可以使用协方差,因为一​​个函数 returns a Foo 也可以看作是 returns 和 object.

的函数

要了解发生了什么,请查看 Func<T,TResult> 委托的定义:

public delegate TResult Func<in T, out TResult>(
    T arg
)

如你所见,它的第一个类型参数T是一个in参数。因此,您不能将 out 参数用作 Func 的第一个类型参数。第二个类型参数 TResultout,因此将 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);
    }    
}

Demo.