2010-02-02 19 views
8

Bir değerin, değer türü için varsayılan değer olup olmadığını kontrol edebilmek istiyorum. İdeal olarak, ben söylemek istiyorum:Varsayılan değer, jenerik türleri kullanarak kontrol edin

DoSomething<TValue>(TValue value) { 
    if (value == default(TValue)) { 
     ... 
    } 
} 

Ancak derleyici bu TValue ve TValue üzerinde == karşılaştırma yapamaz şikayet ediyor. Bu konuda gitmek için daha zarif/doğru yolu

DoSomething<TValue>(TValue value) { 
    if (value == null || value.Equals(default(TValue))) { 
     ... 
    } 
} 

var mı: Bu defa ile geldim iyi çözüm nedir?

cevap

37
public bool EqualsDefaultValue<T>(T value) 
{ 
    return EqualityComparer<T>.Default.Equals(value, default(T)); 
} 
4

Sınıf kısıtlamasını atın ve çalışmalıdır. Veya yalnızca değer türlerini istiyorsanız bunu yapabilirsiniz.

public void Test<T>(T instance) where T : struct, IEquatable<T> 
{ 
    if (instance.Equals(default(T))) 
    { 

    } 
} 
+4

Eğer 'class' kısıtlama atmak durumunda size de sadece null' ... –

+0

@Marc' karşı kontrol edebilir - Ben bir konudur bu noktada biliyorum tercihi. – ChaosPandion

+0

Bu çalışmayı değer ve sınıf türleri de dahil olmak üzere herhangi bir tür için yapmayı umuyoruz. – StriplingWarrior

1

Senin sorunun (hayır kısıtlaması ile) genric tip herhangi bir tür için "derlenebilir" olmak zorunda olmasıdır. Her türün bir == işleci olmadığı için kodunuz derlenmeyecektir.

Bunu çözümlemenin bir yolu, kodun başka türlerle çalışmasını istediğinizi öneren varsayılan (TValue) kullandığınız için bir sınıf kısıtlaması eklemektir. (Aksi takdirde sadece) yerine varsayılan (TValue null'u kullanabilirsiniz. Bir çözüm Bryan Watts

bool DoSomething<TValue>(TValue value) { 
    return EqualityComparer<TValue>.Default.Equals(value, default(TValue)); 
} 

önerir veya ekleme bir uzantısı yöntemiyle

bool IsDefault<TValue>(this TValue value) { 
    return EqualityComparer<TValue>.Default.Equals(value, default(TValue)); 
} 
0

içinde tamamlamayı olabilir ne benzer bir şey olabilir Hepimiz sadece oluşturmak ve milyonlarca küçük h korumak için seviyorum

static public class MyGenericHelper 
{ 
    static public bool EqualsByValue<T>(T x, T y) 
    { 
     return EqualityComparer<T>.Default.Equals(x, y); 
    } 

    static public bool EqualsByReference<T>(T x, T y) 
    { 
     if (x is ValueType) return EqualityComparer<T>.Default.Equals(x, y) // avoids boxing 

     return Object.ReferenceEquals(x, y); 
    } 
} 

: cevaplar burada yayınlanan, biz de biz değer veya referans eşitlik istiyorum belirtmek gerekir düşünüyorum ELPER böyle yöntemler öyle değil: ->

+0

'typeof (T) .IsValueType', x okunabilirlik ve performans açısından 'x, ValueType' olarak tercih edilebilir. Yanlış mıyım? – StriplingWarrior

+1

Belki de okunabilirlik bazen bir tat meselesidir. : -> ... 'x ValueType 'sadece sezgisel olarak" daha hızlı hisseder "çünkü, typeof (T) .IsValueType' oldukça ağır 'Type' örneğini almak zorundadır ve Reflektör,' .IsValueType' olduğunu ortaya çıkarır. 'RuntimeType' uygulamasında uygulanan sanal bir yöntem, sonuçta dışsal bir şey çağırır. Ama sonra kim yargılayacağım, içeriden biri değilim. Aynı talimatlara bile derlerler. Belki de yeni bir soru. ;-) ... Ya da eğer önemliyse, bazı performans testleri yapabilirsin. – herzmeister

+0

Çok önemli değil ama merak ettim, bu yüzden hızlı bir test yaptım ve haklısınız! 'x, ValueType’ın üçte bir uzunluğunu alır. – StriplingWarrior

İlgili konular