Jon Skeet Inspects ReSharper adlı web seminerini izledikten sonra , yinelemeli kurucu çağrıları ile biraz oynamaya başladım ve aşağıdaki kodun geçerli C # kodu olduğunu (geçerli derken derlediğini kastediyorum) buldum.
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() { }
}
Muhtemelen hepimizin bildiği gibi, alan başlatma derleyici tarafından kurucuya taşınır. Yani bir alanınız int a = 42;varsa a = 42, tüm kurucularda olacaktır. Ancak, başka bir kurucuyu çağıran bir kurucunuz varsa, yalnızca çağrıda başlatma koduna sahip olacaksınız.
Örneğin, varsayılan kurucuyu çağıran parametrelere sahip bir kurucunuz varsa, atama a = 42yalnızca varsayılan kurucuda olacaktır.
İkinci durumu göstermek için sonraki kod:
class Foo
{
int a = 42;
Foo() :this(60) { }
Foo(int v) { }
}
Aşağıdakileri derler:
internal class Foo
{
private int a;
private Foo()
{
this.ctor(60);
}
private Foo(int v)
{
this.a = 42;
base.ctor();
}
}
Yani asıl sorun, bu sorunun başında verilen kodumun şu şekilde derlenmiş olmasıdır:
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şlatmayı nereye koyacağına karar veremez ve sonuç olarak onu hiçbir yere koymaz. Ayrıca baseyapıcı çağrılarının olmadığını unutmayın . Elbette, hiçbir nesne oluşturulamaz ve StackOverflowExceptionbir örnek oluşturmaya çalışırsanız her zaman sonuçta kalırsınız Foo.
İki sorum var:
Derleyici neden yinelemeli yapıcı çağrılarına izin veriyor?
Neden böyle bir sınıf içinde başlatılan alanlar için derleyicinin bu tür davranışını gözlemliyoruz?
Bazı notlar: ReSharper sizi uyarıyor Possible cyclic constructor calls. Dahası, Java'da bu tür yapıcı çağrıları olay derlenmez, bu nedenle Java derleyicisi bu senaryoda daha kısıtlayıcıdır (Jon bu bilgiden web seminerinde bahsetmiştir).
Bu, bu soruları daha ilginç hale getirir, çünkü Java topluluğu ile ilgili olarak, C # derleyicisi en azından daha moderndir.
Bu, C # 4.0 ve C # 5.0 derleyicileri kullanılarak derlendi ve dotPeek kullanılarak derlendi .