问题理解C#中与泛型的协方差 [英] Problem understanding covariance contravariance with generics in C#

查看:65
本文介绍了问题理解C#中与泛型的协方差的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不明白为什么下面的C#代码无法编译。

I can't understand why the following C# code doesn't compile.

如您所见,我有一个静态的泛型方法,带有<$ c的东西$ c> IEnumerable< T> 参数(和 T 约束为 IA 接口),并且不能将该参数隐式转换为 IEnumerable< IA>

As you can see, I have a static generic method Something with an IEnumerable<T> parameter (and T is constrained to be an IA interface), and this parameter can't be implicitly converted to IEnumerable<IA>.

解释是什么? (我不是在寻找解决方法,只是为了了解为什么它不起作用。)

What is the explanation? (I don't search for a workaround, just to understand why it doesn't work).

public interface IA { }
public interface IB : IA { }
public class CIA : IA { }
public class CIAD : CIA { }
public class CIB : IB { }
public class CIBD : CIB { }

public static class Test
{
    public static IList<T> Something<T>(IEnumerable<T> foo) where T : IA
    {
        var bar = foo.ToList();

        // All those calls are legal
        Something2(new List<IA>());
        Something2(new List<IB>());
        Something2(new List<CIA>());
        Something2(new List<CIAD>());
        Something2(new List<CIB>());
        Something2(new List<CIBD>());
        Something2(bar.Cast<IA>());

        // This call is illegal
        Something2(bar);

        return bar;
    }

    private static void Something2(IEnumerable<IA> foo)
    {
    }
}

我在 Something2(bar)行中遇到错误:


参数1:无法从 System.Collections.Generic.List
转换为 System.Collections.Generic.IEnumerable

Argument 1: cannot convert from 'System.Collections.Generic.List' to 'System.Collections.Generic.IEnumerable'


推荐答案

错误消息提供的信息不足,这是我的错。抱歉。

The error message is insufficiently informative, and that is my fault. Sorry about that.

您遇到的问题是协方差仅适用于引用类型这一事实的结果。

The problem you are experiencing is a consequence of the fact that covariance only works on reference types.

您现在可能会说但是 IA 是参考类型。是的。但是您并不是说 T 等于 IA 。您说 T 实现 IA 一个值的类型类型可以实现接口。因此,我们不知道协方差是否有效,因此我们不允许。

You're probably saying "but IA is a reference type" right now. Yes, it is. But you didn't say that T is equal to IA. You said that T is a type which implements IA, and a value type can implement an interface. Therefore we do not know whether covariance will work, and we disallow it.

如果您希望协方差有效,则必须告诉编译器类型参数是引用类型。具有 class 约束以及 IA 接口约束。

If you want covariance to work you have to tell the compiler that the type parameter is a reference type with the class constraint as well as the IA interface constraint.

错误消息确实应该说不可能进行转换,因为协方差需要保证引用类型,因为这是根本问题。

The error message really should say that the conversion is not possible because covariance requires a guarantee of reference-type-ness, since that is the fundamental problem.

这篇关于问题理解C#中与泛型的协方差的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆