Not: Bu, Roslyn'de düzeltilmiş gibi görünüyor
Cevabımı yazarken bu soru ortaya çıktı bu bir bir çağrışımsal bahsediyor boş-kaynaştırma operatörü .
Hatırlatma olarak, boş birleştirici operatörün fikri, formun bir ifadesi
x ?? y
önce değerlendirir x
, sonra:
- Değeri
x
null isey
, değerlendirilir ve bu ifadenin sonucudur - Değeri ise
x
boş olmayan,y
bir değil, değerlendirilir ve değerix
derleme zamanı türüne dönüşüm sonra, ifade sonucudury
gerektiğinde
Şimdi genellikle bir dönüşüme gerek yoktur, ya da sadece boş değer türünden boş değer olmayan bir biçime - genellikle türler aynıdır ya da yalnızca (diyelim) int?
ile int
. Ancak, can kendi örtük dönüştürme operatörleri oluşturmak ve bu gerektiğinde kullanılır.
Basit bir durum için x ?? y
, garip bir davranış görmedim. Ancak,(x ?? y) ?? z
bazı kafa karıştırıcı davranışlar görüyorum.
İşte kısa ama eksiksiz bir test programı - sonuçlar yorumlarda:
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;
}
}
Bu yüzden üç özel değer türümüz var A
, B
veC
C B, C, A ve B, A ile ilgili dönüşüm ile,
Hem ikinci hem de üçüncü vakayı anlayabiliyorum ... ama neden ilk durumda ekstradan A'ya B dönüşümü var? Özellikle, gerçekten aynı şey olması ilk vaka ve ikinci durumda umuyordum - bu sadece tüm sonra, yerel bir değişkene bir ifade ayıklanması ediyor.
Neler olup bittiğini merak eden var mı? Ben C # derleyicisi söz konusu olduğunda "hata" ağlamak için son derece hesistant, ama ne olup bittiği gibi güdük ...
DÜZENLEME: Tamam, yapılandırıcının yanıtı, bunun bir hata olduğunu düşünmem için daha fazla neden veren, neler olup bittiğine dair nazik bir örnek. EDIT: Örnek şimdi iki boş birleştirici operatöre bile gerek yok ...
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;
}
}
Bunun çıktısı:
Foo() called
Foo() called
A to int
Foo()
Burada iki kez çağrılan gerçek benim için çok şaşırtıcı - ifadenin iki kez değerlendirilmesi için herhangi bir neden göremiyorum .
C? first = ((B?)(((B?)x) ?? ((B?)y))) ?? ((C?)z);
. Şunları alacaksınız:Internal Compiler Error: likely culprit is 'CODEGEN'
(("working value" ?? "user default") ?? "system default")