2010-02-02 12 views
8

मैं यह जांचने में सक्षम होना चाहता हूं कि कोई मान उसके मान प्रकार के लिए डिफ़ॉल्ट है या नहीं। आदर्श रूप में, मैं कहना चाहता हूँ:जेनेरिक प्रकारों का उपयोग कर डिफ़ॉल्ट मान जांच

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

हालांकि, संकलक शिकायत है कि यह TValue और TValue पर एक == तुलना नहीं कर सकते।

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

वहाँ एक और अधिक सुरुचिपूर्ण/सही इस बारे में जाने के लिए रास्ता नहीं है: यह सबसे अच्छा समाधान का है कि मैं अब तक के साथ आ गया है?

उत्तर

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

कक्षा की बाधा में फेंको और इसे काम करना चाहिए।

public void Test<T>(T instance) where T : class 
{ 
    if (instance == default(T)) 
    { 

    } 
} 

या यदि आप केवल मूल्य प्रकार चाहते हैं तो आप यह कर सकते हैं।

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

    } 
} 
+4

यदि आप 'कक्षा' बाधा में फेंकते हैं तो आप 'शून्य' के खिलाफ भी जांच सकते हैं ... –

+0

@Marc - मुझे पता है, इस बिंदु पर यह एक मामला है वरीयता का – ChaosPandion

+0

मैं इस काम को मूल्य और वर्ग प्रकार सहित किसी भी प्रकार के लिए बनाने की उम्मीद कर रहा हूं। – StriplingWarrior

1

आपका समस्या यह है कि एक genric प्रकार (कोई बाधा के साथ) किसी भी प्रकार के लिए "compilable" हो गया है है। चूंकि सभी प्रकारों में एक == ऑपरेटर नहीं है, इसलिए आपका कोड संकलित नहीं होगा।

इसे हल करने का एक तरीका क्लास बाधा को जोड़ना है, हालांकि जब आप डिफ़ॉल्ट (टीवीएयू) का उपयोग करते हैं तो यह सुझाव देगा कि आप कोड को अन्य प्रकारों के साथ काम करना चाहते हैं। (अन्यथा सिर्फ डिफ़ॉल्ट (TValue के बजाय अशक्त का उपयोग करें) एक समाधान क्या ब्रायन वत्स पता चलता है

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

या आप एक विस्तार विधि

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

को जोड़ना में यह लपेट सकता है ऐसी ही कुछ हो सकता है। जवाब यहां पोस्ट, मुझे लगता है कि हम भी अगर तुम हम मूल्य या संदर्भ समानता चाहते हैं निर्दिष्ट करने के लिए सक्षम होना चाहिए:

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); 
    } 
} 

हम सब सिर्फ बना सकते हैं और एक छोटे से असंख्य ज बनाए रखने के लिए प्यार इस तरह के एल्पर विधियों हम नहीं हैं: ->

+0

ऐसा लगता है कि 'टाइपऑफ (टी) IsValueType' पठनीयता और प्रदर्शन दोनों के मामले में 'x वैल्यू टाइप' के लिए बेहतर होगा। क्या मै गलत हु? – StriplingWarrior

+1

शायद पठनीयता कभी-कभी स्वाद का विषय है। : -> ... 'x वैल्यू टाइप टाइप है 'सिर्फ मेरे लिए" तेजी से लगता है ", क्योंकि' टाइपोफ (टी) IsValueType 'को काफी भारी' टाइप 'उदाहरण पुनर्प्राप्त करना है, और परावर्तक से पता चलता है कि' IsValueType ' संपत्ति एक वर्चुअल विधि को कॉल करती है जो 'रनटाइम टाइप' में लागू होती है अंतत: कुछ बाहरी कहती है। लेकिन फिर मैं न्याय करने के लिए कौन हूं, मैं अंदरूनी नहीं हूं। वे एक ही निर्देशों को संकलित भी कर सकते हैं। शायद यह एक अच्छा नया सवाल है। ;-) ... या यदि आप महत्वपूर्ण हैं तो आप कुछ प्रदर्शन परीक्षण स्वयं कर सकते हैं। – herzmeister

+0

यह महत्वपूर्ण नहीं है, लेकिन मैं उत्सुक था, इसलिए मैंने एक त्वरित परीक्षण किया और आप सही हैं! 'x वैल्यू टाइप 'लगभग एक तिहाई लंबा लगता है। – StriplingWarrior

संबंधित मुद्दे