2010-09-14 24 views
5

C# Türünün varsayılan değerini almak için default(T)'u kullanabilirim. System.Type'dan çalışma zamanında varsayılan türü almam gerekiyor. Bunu nasıl yapabilirim?Bir türle nasıl varsayılan (T) çağırabilirim?

E.g. Bu çizgisinde bir şey (hangi çalışmıyor) Eğer bir ifade ağacı oluşturmak için çalışıyorsanız

var type = typeof(int); 
var defaultValue = default(type); 

cevap

9

Referans türü için null numaralı bir döndürme türünde, bir değer türü için, Activator.CreateInstance kullanmayı deneyebilir veya türün varsayılan yapıcısını çağırabilirsiniz.

public static object Default(Type type) 
{ 
    if(type.IsValueType) 
    { 
     return Activator.CreateInstance(type); 
    } 

    return null; 
} 
+1

Sorularımı yazdıktan kısa bir süre sonra 'return İfadesi ile geldim. Lambda > (Expression.Convert (Expression.Default (type), typeof (object))) Compile()(); ', ama seninki çok daha güzel. – GiddyUpHorsey

+0

@Giddy: Bunu yapmak için çok pahalı bir yol olurdu, çünkü ifade ağacını IL'ye (ve JIT'in bunu her zaman derleme yapmak zorunda kalacak) derlediğine göre. –

+0

Evet, katılıyorum. Bu yüzden kullanmıyorum ve bunun yerine madgnome'un çözümünü kullanıyorum. Her ne kadar, daha az ve daha okunaklı bir koddu, performans değil, beni kullanması için beni zorladı.Performansım senaryo için çok büyük değil. – GiddyUpHorsey

6

, kullanmak Expression.Default:

Expression expression = Expression.Default(type); 

bir diğer yolu yapabileceği bu oldukça kolay olacaktır:

object defaultValue = Array.CreateInstance(type, 1).GetValue(0); 

Çirkin ama o, bir null türü varsayılan değerini almak zor olduğunu unutmayın :) çalışacağız o olacak bir şekilde lull boş bir referans için kutulu. açıklamalarda belirtildiği gibi

, orada bu eşdeğer olmayan bazı karanlık senaryolar (void ve işaretçi türleri), ancak bunlar köşe durumlarda :)

oldukça kolay
+1

Ben Mindscape Lightspeed ile kullanmak için ifade ağaçlar üreten değilim, ama onların sorgu sağlayıcı 'DefaultExpression' desteklemiyor, bu yüzden bir' ConstantExpression' içine koymak gerçek değerini gerekir. – GiddyUpHorsey

+0

En ufak bir nitriliğin en zayıfı olan behviour, işaretçi türleri için farklıdır. 'default (int *)' intPtr.Zero'yu döndürürken, Default (typeof (int *)) 'a basar. Bulduğum diğer bir belirsiz alan 'System.Void' için, 'default (void') yapamazken,' Default (typeof (void) ') null değerini döndürür. Hayır biggie, kimse ilgilenmek isterse .. – nawfal

+0

@nawfal: Bu etki için bir not eklendi, teşekkürler. –

3

, sadece dikkate almak 2 vaka var konum :

  • referans tipleri: varsayılan değer her zaman boş
  • değer türleri geçerli: kolayca Activator.CreateInstance

    kullanarak bir örnek oluşturabilir

Activator.CreateInstance yerine FormatterServices.GetUninitializedObject kullanmayı düşünebilirsiniz, muhtemelen daha hızlıdır.

+0

Kodunuzu çalıştırmayı denediniz mi? İşe yaramaz ve bunun nedeni, değer türlerinin (normalde) varsayılan bir kurucu içermemesidir. C# içinde yaparlar, ama bu bir kurgudur; CLR seviyesinde hiçbiri yoktur ve IL'de initobj kullanılmıştır. –

+0

@Pavel, haklısın, gerçek bir varsayılan kurucunun olmadığını farketmedim ... Activator.CreateInstance olarak değiştirdim ve gayet iyi çalışıyor –

İlgili konular