什么使 ValueTuple 协变?

Hei*_*nzi 37 c# covariance valuetuple

这在 C# 7.3 (Framework 4.8) 中正确编译:

(string, string) s = ("a", "b");
(object, string) o = s;
Run Code Online (Sandbox Code Playgroud)

我知道这是以下内容的语法糖,它也可以正确编译:

ValueTuple<string, string> s = new ValueTuple<string, string>("a", "b");
ValueTuple<object, string> o = s;
Run Code Online (Sandbox Code Playgroud)

所以,看起来 ValueTuples 可以被协变分配,这太棒了

不幸的是,我不明白为什么:我的印象是 C#只支持接口和委托的协变ValueType都不是。

事实上,当我尝试用我自己的代码复制这个功能时,我失败了:

struct MyValueTuple<A, B>
{
    public A Item1;
    public B Item2;

    public MyValueTuple(A item1, B item2)
    {
        Item1 = item1;
        Item2 = item2;
    }
}

...

MyValueTuple<string, string> s = new MyValueTuple<string, string>("a", "b");
MyValueTuple<object, string> o = s;
// ^ Cannot implicitly convert type 'MyValueTuple<string, string>' to 'MyValueTuple<object, string>'
Run Code Online (Sandbox Code Playgroud)

那么,为什么ValueTuples 可以协变赋值,而MyValueTuples 不能呢?

Gar*_*tty 27

我相信这里实际发生的是一个解构任务。元组赋值将尝试隐式转换它的组件,因为可以赋值stringobject,这就是这里发生的事情。

该语言支持具有相同元素数量的元组类型之间的赋值,其中每个右侧元素都可以隐式转换为其对应的左侧元素。分配不考虑其他转换。

来源

在sharplab.io上查看

  • 我刚刚在 SharpLab 上尝试过,果然[它确实做到了这一点](https://sharplab.io/#v2:D4AQTAjAsAUCDMACciDCiDetE+UkALIgLIAUAlJtrjaSBAAwA0yjlAzogLyKkBEAQz4s+AIz7kA3NRo5SAe1EArAKYBjAC4t6DSvO6J20mLNz0AnAqkzEAX1i2gA) 。 (4认同)
  • 只是为了强调一下,在OP的原始示例中,如果将`s`更改为`(string, object)`类型,则会导致转换错误,表明项目之间正在发生隐式转换,并且string可以隐式转换为字符串,但反之则不然。 (3认同)