SORU
20 Mayıs 2013, PAZARTESİ


Neden özyinelemeli yapıcı bir çağrı geçersiz kılmaz C# kodu derlemek?

Semineri izledikten sonraJon Skeet Inspects ReSharperKoydum biraz oynamaya başladı aşağıdaki kodu geçerli değil bu aramalar ve bulunan, C özyinelemeli yapıcı# kodu (geçerli derler yani).

class Foo
{
    int a = null;
    int b = AppDomain.CurrentDomain;
    int c = "string to int";
    int d = NonExistingMethod();
    int e = Invalid<Method>Name<<Indeeed();

    Foo()       :this(0)  { }
    Foo(int v)  :this()   { }
}

Hepimizin bildiği gibi, alan başlatma derleyici tarafından kurucu taşındı. Eğer öyleyse int a = 42; gibi bir alan varsa a = 42 olacaktümkurucular. Ama eğer başka bir yapıcısının çağrılması varsa, sadece biri aradı başlatma kodu olacak.

Eğer parametreleri varsayılan kurucu çağırmak kurucu varsa, örneğin, yalnızca varsayılan kurucu a = 42 atama olacak.

İkinci durumda göstermek için, bir sonraki kodu:

class Foo
{
    int a = 42;

    Foo() :this(60)  { }
    Foo(int v)       { }
}

Derler:

internal class Foo
{
    private int a;

    private Foo()
    {
        this.ctor(60);
    }

    private Foo(int v)
    {
        this.a = 42;
        base.ctor();
    }
}

Asıl sorun, benim kod, bu sorunun başında verilen, derlenmiş.

internal class Foo
{
    private int a;
    private int b;
    private int c;
    private int d;
    private int e;

    private Foo()
    {
        this.ctor(0);
    }

    private Foo(int v)
    {
        this.ctor();
    }
}

Gördüğünüz gibi, derleyici alan başlatma nereye koymak için karar veremez ve, sonuç olarak, herhangi bir yere koymaz. Ayrıca not base yapıcı çağrıları vardır. Tabii ki, hiçbir nesne oluşturulabilir ve her zaman Foo bir örneğini oluşturmaya çalışacağız StackOverflowException ile sona erecek.

İki sorum var:

Neden derleyici kurucu aramalar özyinelemeli izin hiç?

Neden alanları, bu sınıf içinde başlatılan için derleyici böyle bir davranış gözlemek?


Bazı notlar: ReSharper Possible cyclic constructor calls ile sizi uyarır. Ayrıca, Java bu tür yapıcı çağrıları Java derleyicisi bu senaryoda (Jon Semineri bu bilgileri söz) daha kısıtlayıcı yüzden derleme olay olmaz.

Bu soru daha ilginç, toplum Java saygım var çünkü ile yapar, C# derleyicisien azındandaha modern.

Bu C# 4.0 C# 5.0 Derleyiciler kullanarak derlendi ve dotPeek kullanarak decompiled.

CEVAP
20 Mayıs 2013, PAZARTESİ


İlginç bulacaksınız.

Gerçekten örnek kurucular: iki tür insan var gibi görünüyor

  1. Bir örnek, başka bir örneği kurucu kurucuaynı türden, : this( ...) sözdizimi ile.
  2. Bir örneği olan zincirleri bir örneği kurucu kurucutemel sınıf. Bu kurucular hayır chainig : base() varsayılan olduğu belirtilen, nerede örneği içerir.

(Özel bir durum örneği System.Object yapıcı önem vermedim. System.Object hiçbir temel sınıf vardır! Ama System.Object ya da alan yok.)

Sınıf mevcut olabilecek örnek alan başlatıcılar, türü örnek oluşturucular cesedi başında içine kopyalanması gerekir2.yukarıda, hiçbir örnek ise tür markalar1.alan atama kodu lazım.

C gerek yok yani görünen o ki,# derleyici türü kurucular bir analiz yapmak1.eğer döngüleri orada görmek istiyor.

Şimdi örnek bir durum verirtümörnek oluşturucular türü vardır1.. Bu durumda alan initaializer kodu herhangi bir yere koymak olması gerekmez. Çok derin bir analiz değildir, gibi görünüyor.

Tüm örnek kurucular türü çıkıyor1.daha erişilebilir yapıcı olan temel sınıfından türetmek. Temel sınıf olmayan kapalı olmalı, değil mi? Eğer private tek örneği kurucular ile bir sınıf yazarsanız, örneğin, insanlar hala eğer türetilmiş bir sınıf örneği tüm kurucular türü olarak yaparlarsa, senin sınıfından türetmek1.yukarıda. Ancak, yeni nesne oluşturma bir ifade asla, elbette bitecek. Türetilmiş bir sınıf örneğini oluşturmak için, bir" ve System.Runtime.Serialization.FormatterServices.GetUninitializedObject yöntem. gibi şeyler kullanın "hile olurdu

Başka bir örnek: System.Globalization.TextInfo sınıfı internal örnek tek bir kurucusu vardır. Ama yine de bu teknik ile bir derleme mscorlib.dll dışında bu sınıftan türetmek.

Son olarak, ilgili

Invalid<Method>Name<<Indeeed()

sözdizimi. C göre# kural, bu gibi okunabiliyor

(Invalid < Method) > (Name << Indeeed())

sol-shift operatörü, çünkü << küçüktür operatörü < ve büyüktür operatörü > hem daha yüksek önceliğe sahiptir. Son iki operarors aynı önceliğe sahiptir, ve bu nedenle sol-ilişkisel kural tarafından değerlendirilir. Eğer bu tip olsaydı

MySpecialType Invalid;
int Method;
int Name;
int Indeed() { ... }

ve eğer MySpecialType ** 37, ifade, sonra (MySpecialType, int) aşırı tanıttı

Invalid < Method > Name << Indeeed()

yasal ve anlamlı olurdu.


Benim görüşüme göre, eğer derleyici bu senaryoda bir uyarı olursa daha iyi olur. Örneğin, hiç IL çevrilir alan başlatıcı satır ve sütun sayısı unreachable code detected ve işaret ediyor olabilir.

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • GavinMichaelBooth

    GavinMichael

    26 AĞUSTOS 2006
  • Random Act of Kindness Video Contest

    Random Act o

    18 EYLÜL 2012
  • Paulo Bautista

    Paulo Bautis

    21 Aralık 2008