SORU
6 HAZİRAN 2011, PAZARTESİ


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, ydeğ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
7 HAZİRAN 2011, Salı


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!

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • NPR

    NPR

    22 NİSAN 2006
  • Shylo Sharity

    Shylo Sharit

    27 EKİM 2011
  • ThePhestor

    ThePhestor

    22 Mart 2011