web-dev-qa-db-ja.com

ValueTupleを共変にするものは何ですか?

これはC#7.3(フレームワーク4.8)で正しくコンパイルされます。

(string, string) s = ("a", "b");
(object, string) o = s;

これは次の構文シュガーであることを知っています。これも正しくコンパイルされます。

ValueTuple<string, string> s = new ValueTuple<string, string>("a", "b");
ValueTuple<object, string> o = s;

したがって、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>'

それでは、なぜValueTuplesを共変的に割り当てることができますが、MyValueTuplesは割り当てられないのですか?

35
Heinzi

ここで実際に起こっていることは、破壊的な任務だと思います。タプル割り当ては、そのコンポーネントを暗黙的に変換しようとします。stringobjectに割り当てることが可能であるため、ここでそれが行われます。

この言語は、同じ数の要素を持つタプル型間の割り当てをサポートしています。各右側要素は、対応する左側要素に暗黙的に変換できます。他の変換は割り当てでは考慮されません。

ソース

sharplab.ioで確認してください

25
Gareth Latty