为什么这个 C# 泛型委托不分配?

Ian*_*Ian 4 c# generics

我想要一个对返回泛型接口实例的委托的引用,其中类型参数是协变的。T如果我在调用时指定类型,Get那么它可以编译正常。但在 内部Get,我无法完成看起来等效的任务 - 尽管T受到限制IItem

它说...

无法将类型“System.Func<MyNamespace.A>”隐式转换为“System.Func<MyNamespace.IA<MyNamespace.IItem>>”。存在显式转换(您是否缺少强制转换?)

为什么是这样?

using System;
using System.Collections.Generic;
using System.Linq;

namespace MyNamespace
{
    public interface IA<out T>
    {
        IEnumerable<T> f();
    }
    
    public class A<T> : IA<T>
    {
        public IEnumerable<T> f()
        {
            return Enumerable.Empty<T>();
        }
    }
    
    public interface IItem {}
    public class Item : IItem {}
    
    public static class Program
    {
        public static void Main(string[] args)
        {   
            Func<IA<IItem>> a = Get<Item>();
        }
        
        public static Func<IA<T>> Get<T>() where T : IItem
        {
            var x = () => new A<T>();
            
            //Doesn't compile
            Func<IA<IItem>> a = x;
            
            return x;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 5

协方差仅适用于引用类型 - 如果T值类型实现IItem.

为了使代码编译,您需要做的就是将其限制T为引用类型:

public static Func<IA<T>> Get<T>() where T : class, IItem
Run Code Online (Sandbox Code Playgroud)

作为一个稍微简单的示例(具有较少的泛型),我们可以使用IConvertiblestringand实现的int

Func<string> x = () => "";
Func<int> y = () => 0;

// This is fine, as string is a
// reference type implementing IConvertible
Func<IConvertible> x2 = x;

// This doesn't compile, because the
// covariant conversion isn't available:
// int is a value type (even though it
// implements IConvertible)
Func<IConvertible> y2 = y;
Run Code Online (Sandbox Code Playgroud)