gpt4 book ai didi

C# 为什么这里不需要显式强制转换?

转载 作者:行者123 更新时间:2023-11-30 13:25:34 25 4
gpt4 key购买 nike

如果没有显式转换,这段代码如何工作?

static void Main()
{
IList<Dog> dogs = new List<Dog>();
IEnumerable<Animal> animals = dogs;
}

我说的是这一行:

IEnumerable<animal> animals = dogs;

你可以在这里看到我可以在没有显式转换的情况下传递变量 dogs。但这怎么可能呢?为什么编译器允许我这样做?我不应该先像这样进行转换吗:

IEnumerable<Animal> animals = (List<Dog>) dogs;

代码将使用显式转换和不使用显式转换,但我不明白为什么它允许我在不使用显式转换的情况下将狗分配给动物引用变量。

最佳答案

IEnumerable<T>covariant interface .这意味着存在从 IEnumerable<T1> 的隐式身份转换至 IEnumerable<T2>只要存在来自 T1隐式引用转换身份转换T2 .查看documentation on conversions有关此术语的更多详细信息。

最常见的情况是 T2T1 的基类(直接或间接) ,或者是 T1 的接口(interface)实现。如果T1也是如此和 T2是同一类型,或者如果 T2dynamic .

在您的例子中,您使用的是 IList<Dog> , 和 IList<T>工具 IEnumerable<T> .这意味着任何 IList<Dog>也是一个 IEnumerable<Dog> ,因此存在对 IEnumerable<Animal> 的隐式引用转换.

需要注意的一些重要事项:

  • 只有接口(interface)和委托(delegate)类型可以是协变或逆变的。例如,List<T>不是协变的,也不可能是。例如,你不能写:

    // Invalid
    List<Animal> animals = new List<Dog>();
  • 并非所有 接口(interface)都是协变或协变的。例如,IList<T>不是协变的,所以这也是无效的:

    // Invalid
    IList<Animal> animals = new List<Dog>();
  • Variance 不适用于值类型,因此这是无效的:

    // Invalid
    IEnumerable<object> objects = new List<int>();

只有在安全的情况下才允许通用变体:

  • 协方差依赖于类型参数仅出现在任何签名的“out”位置,即值可以来自实现,但永远不会被接受。
  • 逆变依赖于类型参数只出现在任何签名的“输入”位置,即值可以传递到实现中,但永远不会返回

当签名接受一个本身是逆变的参数时,它会变得有点困惑——即使参数通常是一个“输入”位置,它也会被逆变逆转。例如:

public interface Covariant<out T>
{
// This is valid, because T is in an output position here as
// Action<T> is contravariant in T
void Method(Action<T> input);
}

不过,一定要阅读链接的文档以获取更多信息!

关于C# 为什么这里不需要显式强制转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49597406/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com