2010-04-30 15 views
5

Aşağıdaki kod, "Widget, public parametless constructor ile soyut olmayan bir tip olmalıdır" üreterek derlenemiyor. Derleyicinin ihtiyaç duyduğu tüm bilgilere sahip olduğunu düşünürdüm. Bu bir hata mı? Bir gözetim mi? Yoksa bunun geçerli olmayacağı bir senaryo var mı?Neden yeni() jenerik kısıtlayıcı, kurucudaki isteğe bağlı parametrelerle bir sınıftan memnun değil?

public class Factory<T> where T : new() 
{ 
    public T Build() 
    { 
     return new T(); 
    } 
} 

public class Widget 
{ 
    public Widget(string name = "foo") 
    { 
     Name = name; 
    } 

    public string Name { get; set; } 
} 

public class Program 
{ 
    public static void Main() 
    { 
     var widget = new Widget(); // this is valid 
     var factory = new Factory<Widget>(); // compiler error 
    } 
} 
+0

Paging Eric Lippert .... Bence bu derleyici bir özellik olan isteğe bağlı parametrelere iner, ancak CLR olan genel kısıtlamalar. Bu yüzden isteğe bağlı parametreler derleyici tarafından değiştirilir ve JIT yalnızca (gerekli) parametreleri görür. – Richard

+0

@Richard: Temelde konu bu. İsteğe bağlı parametreler de, tam da bu nedenle, sürüm oluşturma için bazı garip yan etkileri var ... –

cevap

7

Mantıksal olarak çalışması gerekirken, ne yazık ki bunu yapmaz. CLR, kurucunuzu hala parametre tabanlı bir kurucu olarak görür.

Unutmayın, C# isteğe bağlı parametreleri desteklerken, derleme zamanında derleyici düzeyinde yapılır. Altta yatan tür sadece tek bir parametre alan bir kurucu içerir. Bildiğim kadarıyla CLR ile ilgili olarak, "varsayılan parametreleri" aynen böyle nitelikler dönüştürülür:

public Widget(([Optional, DefaultParameterValue("foo")] string name) { // ... 

CLR çok dilli bir çalışma zamanı olduğunu. Jenerikler, tüm diller için CLR seviyesinde çalışmak üzere hazırlanmıştır, bu yüzden kısıtlamalar, varsayılan parametreler olmayan dillerde de doğru olmalıdır. Diller, OptionalAttribute veya DefaultParameterValueAttribute öğelerini anlamak için gerekli değildir, bu nedenle tüm diller için düzgün şekilde çalışamaz, dolayısıyla izin verilmez.


Düzenleme:

yorumunuza yanıt olarak

:

Ne C# derleyicisi CLR

karşılamak için gerekli kodu üretemez neden anlamıyorum

Teorik olarak, C# derleyici ekibi, özniteliklerle işaretlenmiş bir yapıcı yerine, dilin iki ayrı kurucu oluşturmasını sağlayabilir. Bu, potansiyel olarak, birçok kurucuya patlayabilir, çünkü adlandırılmış parametreler, özellikle birden fazla argüman mevcut olduğunda, pek çok olası "kurucu" (veya metot metodları) kombinasyonları için yetenekler yaratır. Ben şahsen onlar değil, çünkü üretilen API'lar yöntem ve yapıcıların bir bolluğu nedeniyle karışıklık neden olacağından dolayı sevindim, bu da kamu API'sinin onu oluşturan koddan çok farklı görünmesine neden olacaktır. aşağıdaki kurucu atın:

public Widget(
      int id = 0, 
      string name = "foo", 
      float width=1.0f, 
      float height=1.0f, 
      float depth=1.0f 
     ) { // ... 

otomatik burada olası tüm kombinasyonları oluşturmak için mıydı N olmadığından, derleyici, bu tek yapıcısı için kurucular üretmek gerekir! Bunu çağırmak için olası yollar ...

+0

@Joshua: C# derleyici, yukarıda yapıştırılan kodu oluşturur. Bu şekilde çalışır - parametrik olmayan bir kurucu değil, isteğe bağlı bir yapıdır. Ayrıntıları eklemek için düzenleyeceğim ... –

+0

Tamam, teşekkürler, neden işe yaramadığını açıklıyor. Hala parametrik olmayan kurucuyu yaratmanın etkilerinin ne olduğunu merak ediyorum. –

+0

@Joshua: Cevabımın bunun neden potansiyel olarak kötü bir fikir olduğunu açıklamak için düzenledim… Şimdi daha fazla mantıklı mı? Unutmayın, bu sadece isteğe bağlı değildir, ayrıca adlandırılmış parametreleri de kullanabilirsiniz, böylece N parametreleri N demektir! Oluşturulması gereken olası kombinasyonlar ... –

İlgili konular