C# IEnumerable<T> 中的协变/逆变,其中 T 是泛型类型、接口与类

Jak*_*kub 5 c# generics interface covariance

有人理解为什么类的泛型约束与接口不同吗?此代码无法编译:

public interface IInterface
{
}

public class Class<T> where T : IInterface
{
    public void Do()
    {
        IEnumerable<IInterface> ret = GetEnumerable();
    }

    public IEnumerable<T> GetEnumerable()
    {
        return new T[0];
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,通过将 IInterface 更改为类,突然可以编译

public class IInterface
{
}

public class Class<T> where T : IInterface
{
    public void Do()
    {
        IEnumerable<IInterface> ret = GetEnumerable();
    }

    public IEnumerable<T> GetEnumerable()
    {
        return new T[0];
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道我可以使用:

IEnumerable<IInterface> ret = (IEnumerable<IInterface>)GetEnumerable();
Run Code Online (Sandbox Code Playgroud)

但我真的很想知道如果 IInterface 是接口,为什么需要强制转换。

Flo*_*ger 3

真正的问题是,真的有必要吗?

T,在这种特定情况下,应该始终是一个类。

您可以通过额外添加约束来确保这一点class

public interface IInterface
{
    bool Foo { get; set; }
}

public class Class<T> where T : class, IInterface
{
    public void Do()
    {
        var ret = GetEnumerable();

        foreach (var item in ret)
        {
            item.Foo = true; // you can handle the object just if you would have an object of that type.
        }
    }

    public IEnumerable<T> GetEnumerable()
    {
        return new T[0];
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果您删除类约束,它仍然可以工作。然而,如果你将鼠标悬停在它的波浪线上,item.Foo = true就会明白为什么:

在此输入图像描述