注: これはRoslynで修正されたようです
この質問は、 null 合体演算子の結合性について説明している this oneに対する私の回答を書いているときに発生しました。
念のために言っておきますが、null 合体演算子の考え方は、次の形式の式であるということです。
x ?? y
最初に を評価しx
、次に:
- の値
x
が null の場合、y
が評価され、それが式の最終結果になります - の値が
x
null 以外で、y
が評価されず、 の値が式の最終結果である場合、必要に応じx
てコンパイル時の型 に変換されます。y
現在、通常、変換の必要はありません。または、null 許容型から null 非許容型への変換だけです。通常、型は同じか、単に from (たとえば) int?
toint
です。ただし、独自の暗黙的な変換演算子を作成することができ、それらは必要に応じて使用されます。
の単純なケースではx ?? y
、奇妙な動作は見られませんでした。ただし、(x ?? y) ?? z
いくつかの紛らわしい動作が見られます。
短いが完全なテスト プログラムを次に示します。結果はコメントに記載されています。
using System;
public struct A
{
public static implicit operator B(A input)
{
Console.WriteLine("A to B");
return new B();
}
public static implicit operator C(A input)
{
Console.WriteLine("A to C");
return new C();
}
}
public struct B
{
public static implicit operator C(B input)
{
Console.WriteLine("B to C");
return new C();
}
}
public struct C {}
class Test
{
static void Main()
{
A? x = new A();
B? y = new B();
C? z = new C();
C zNotNull = new C();
Console.WriteLine("First case");
// This prints
// A to B
// A to B
// B to C
C? first = (x ?? y) ?? z;
Console.WriteLine("Second case");
// This prints
// A to B
// B to C
var tmp = x ?? y;
C? second = tmp ?? z;
Console.WriteLine("Third case");
// This prints
// A to B
// B to C
C? third = (x ?? y) ?? zNotNull;
}
}
そのため、A から B、A から C、B から C への変換を伴うA
、B
およびの 3 つのカスタム値タイプがあります。C
2 番目のケースも 3 番目のケースも理解できますが、最初のケースに A から B への変換が追加されているのはなぜですか? 特に、最初のケースと 2 番目のケースは同じであると本当に予想していました。結局のところ、式をローカル変数に抽出しているだけなのです。
何が起こっているかについてのテイカーはいますか?C#コンパイラに関しては「バグ」と叫ぶのは非常にためらいますが、何が起こっているのかについては困惑しています...
編集:さて、構成者の答えのおかげで、何が起こっているかのより厄介な例がここにあります。これは、それがバグだと考えるさらなる理由を与えてくれます。編集: サンプルは 2 つの null 合体演算子を必要としません...
using System;
public struct A
{
public static implicit operator int(A input)
{
Console.WriteLine("A to int");
return 10;
}
}
class Test
{
static A? Foo()
{
Console.WriteLine("Foo() called");
return new A();
}
static void Main()
{
int? y = 10;
int? result = Foo() ?? y;
}
}
これの出力は次のとおりです。
Foo() called
Foo() called
A to int
ここで が 2 回呼び出されるという事実は、私にとって非常に驚くべきことです。式が2 回評価さFoo()
れる理由がわかりません。