Meraklı boş birleşiyor operatör özel örtük dönüştürme davranış
Not: bu Roslyn sabit görünüyor
Bu soru null-coalescing operator bu birleşme hakkında konuşuyor this one, cevabımı yazarken ortaya çıktı.
Sadece bir hatırlatma olarak, boş birleşiyor operatörü fikri şeklinde bir ifadesi
x ?? y
ilk değerlendirir x
:
- Eğer
x
değeri null ise,y
değerlendirilir ve bu ifadenin son hali x
değeri boş olmayan,y
değildeğerlendirilmesi,x
değeri gerekirse son ifade,y
derleme zamanı tür bir dönüşüm sonrasında sonucudur
Şimdigenelliklehiç gerek yok bir dönüşüm, ya da sadece bir null türü için null olmayan bir - genellikle bu tür aynı, veya (say) int?
int
. Ancak, senolabilirkendi örtülü dönüşüm operatörleri oluşturmak, ve gerektiğinde kullanılır.
x ?? y
, basit bir durum için herhangi bir garip davranış görmedim. Ancak, (x ?? y) ?? z
ile biraz kafa karıştırıcı davranışlar görüyorum.
Burada kısa ama tam bir test programı - sonuçları yorumlar
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;
}
}
Yani biz üç özel bir değer türleri vardır, A
, B
ve dönüşümler ile C
, B, C, A, B, C
Her ikisi de ikinci bir durum anlayabiliyorum ve üçüncü vaka... amanedenilk durumda B dönüşüm için ekstra Bir var mı? Özellikle, istiyorumgerçektenilk durumda ve ikinci durumda aynı şeyi olması bekleniyor - sadece yerel bir değişken bir ifade, sonuçta ayıklanıyor.
Ne kabul eden var mı? Ağlamak son derece hesistant ben "C geldiğinde"# derleyicisi, ama ne kadar tıkandım... . hata
EDİT: bir hata olduğunu düşünmek bana daha fazla neden veren yapılandırıcı cevabı, Tamam, burada neler olup bittiğini kötü bir örnek, teşekkürler. EDİT: Bu örnek bile iki boş birleşiyor operatörleri artık yardıma ihtiyacı 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;
}
}
Bu çıktı:
Foo() called
Foo() called
A to int
Foo()
iki kez çağrılır aslında benim için son derece şaşırtıcı olduğunu ifade etmek için herhangi bir sebep göremiyorumdeğerlendirdiiki kez.
CEVAP
Bu sorunu çözümlemek için emeği geçen herkese teşekkürler. Net derleyici bir hata. Kaldırdı bir dönüşüm birleşiyor operatörün sol tarafında iki türü null ilgili olduğunda tek başına görünüyor.
Henüz tam olarak nerede yanlış teşhis edemedim. ama "düşürücü" kod oluşturma ilk önce analiz sonra ama ... ifade azaltıyoruz . derleme -- faz null sırasında bir noktada
result = Foo() ?? y;
ahlaki eşdeğer üzeri için: örnek
A? temp = Foo();
result = temp.HasValue ?
new int?(A.op_implicit(Foo().Value)) :
y;
Açıkça yanlış; doğru düşürmek
result = temp.HasValue ?
new int?(A.op_implicit(temp.Value)) :
y;
Benim en iyi tahmin yaptığım analize göre şu ana kadar null iyileştirici raylar buraya gidiyor. Null türünden bir ifade muhtemelen boş olamaz biliyoruz durumlar için görünen null bir doktoru var. Aşağıdaki naif analizler içerir: birincisi. " diyebiliriz
result = Foo() ?? y;
aynı gibi
A? temp = Foo();
result = temp.HasValue ?
(int?) temp :
y;
ve sonra söyleyebiliriz
conversionResult = (int?) temp
aynı gibi
A? temp2 = temp;
conversionResult = temp2.HasValue ?
new int?(op_Implicit(temp2.Value)) :
(int?) null
Ancak doktoru bidonun içinde ve de ki "Hey, bekle bir dakika, biz zaten işaretli o sıcaklığı değil null; gerek yok kontrol etmek için ikinci bir boş zaman diye çağırıyoruz bir kaldırdı dönüşüm operatör". Sadece onları uzakta optimize ederiz
new int?(op_Implicit(temp2.Value))
Sanırım bizi bir yere önbellekleme aslında o kadar optimize formu (int?)Foo()
new int?(op_implicit(Foo().Value))
ama öyle değil aslında optimize formu istiyoruz; istediğimiz optimize formu Foo()-yerine-ile-geçici-ve-sonra-dönüştürülmüş.
C birçok böcek# derleyici önbelleği kötü kararların bir sonucudur. Bilge için bir sözcük:her zaman kullandığınız bir gerçeği önbellek daha sonra, potansiyel olarak ilgili bir şeyler değişmeli bir tutarsızlık yaratıyor. Bu durumda yazılan ilk analizi değiştiğini ilgili bir şey Foo çağrısı() her zaman bir getirme geçici bir. olarak fark edilmelidir
Null C geçişte yeniden yeniden düzenlenmesi çok# 3.0 yaptık. Hata C hata muhtemelen benim kötü olduğu anlamına geliyor# 2.0, C# 3.0 ve 4.0 ama üretir. Üzgünüm!
Bir hata veritabanına girilen alacağım ve bu dili gelecekteki bir sürüm için tamir edebiliriz bakalım. Tekrar teşekkürler analiz için herkes; çok faydalı oldu!
Operatör çok garip bir davranış '...
Ön & C operatör davranış, C , sonrası ...
IDisposable ve "kullanarak" ...
&Quot;boş birleşiyor" JavaScript ...
Orada C Python eşdeğer# boş birleşiyor...