यहां दो मुद्दे हैं: 1) यह देखने के लिए परीक्षण करना कि क्या एक प्रकार अशक्त है; और 2) यह देखने के लिए परीक्षण करना कि कोई वस्तु अशक्त प्रकार का प्रतिनिधित्व करती है या नहीं।
समस्या 1 (एक प्रकार का परीक्षण) के लिए, यहां एक समाधान है जिसे मैंने अपने सिस्टम में उपयोग किया है: TypeIsNullable-check solution
समस्या 2 (किसी ऑब्जेक्ट का परीक्षण) के लिए, डीन चाक का समाधान मूल्य प्रकारों के लिए काम करता है, लेकिन यह संदर्भ प्रकारों के लिए काम नहीं करता है, क्योंकि <T> अधिभार का उपयोग करने से हमेशा गलत रिटर्न मिलता है। चूंकि संदर्भ प्रकार स्वाभाविक रूप से अशक्त हैं, इसलिए संदर्भ प्रकार का परीक्षण हमेशा सही होना चाहिए। कृपया इन शब्दार्थों की व्याख्या के लिए नीचे [["अशक्तता"] नोट देखें। इस प्रकार, यहाँ डीन के दृष्टिकोण के लिए मेरा संशोधन है:
public static bool IsObjectNullable<T>(T obj)
{
// If the parameter-Type is a reference type, or if the parameter is null, then the object is always nullable
if (!typeof(T).IsValueType || obj == null)
return true;
// Since the object passed is a ValueType, and it is not null, it cannot be a nullable object
return false;
}
public static bool IsObjectNullable<T>(T? obj) where T : struct
{
// Always return true, since the object-type passed is guaranteed by the compiler to always be nullable
return true;
}
और यहाँ उपरोक्त समाधान के लिए ग्राहक-परीक्षण कोड में मेरा संशोधन है:
int a = 123;
int? b = null;
object c = new object();
object d = null;
int? e = 456;
var f = (int?)789;
string g = "something";
bool isnullable = IsObjectNullable(a); // false
isnullable = IsObjectNullable(b); // true
isnullable = IsObjectNullable(c); // true
isnullable = IsObjectNullable(d); // true
isnullable = IsObjectNullable(e); // true
isnullable = IsObjectNullable(f); // true
isnullable = IsObjectNullable(g); // true
कारण यह है कि मैंने IsObjectNullable <T> (T t) में डीन के दृष्टिकोण को संशोधित किया है, यह है कि उनका मूल दृष्टिकोण हमेशा संदर्भ प्रकार के लिए गलत है। चूँकि IsObjectNullable जैसी विधि को संदर्भ प्रकार मान को संभालने में सक्षम होना चाहिए और चूँकि सभी संदर्भ प्रकार स्वाभाविक रूप से अशक्त हैं, इसलिए यदि कोई संदर्भ प्रकार या अशक्त पास है, तो विधि हमेशा सही होनी चाहिए।
उपरोक्त दो विधियों को निम्न एकल विधि से बदला जा सकता है और समान आउटपुट प्राप्त कर सकते हैं:
public static bool IsObjectNullable<T>(T obj)
{
Type argType = typeof(T);
if (!argType.IsValueType || obj == null)
return true;
return argType.IsGenericType && argType.GetGenericTypeDefinition() == typeof(Nullable<>);
}
हालाँकि, इस अंतिम, एकल-विधि दृष्टिकोण के साथ समस्या यह है कि जब Nullable <T> पैरामीटर का उपयोग किया जाता है, तो प्रदर्शन प्रभावित होता है। इस एकल विधि की अंतिम पंक्ति को निष्पादित करने में बहुत अधिक प्रोसेसर समय लगता है, क्योंकि कंपाइलर को पहले दिखाए गए दूसरे तरीके को अधिभार चुनने की अनुमति देता है जब एक अशक्त <T> -Type पैरामीटर का उपयोग IsObjectNullable कॉल में किया जाता है। इसलिए, इष्टतम समाधान यहां चित्रित दो-विधि दृष्टिकोण का उपयोग करना है।
CAVEAT: यह विधि मूल रूप से केवल तभी काम करती है जब मूल ऑब्जेक्ट संदर्भ या सटीक प्रतिलिपि का उपयोग करके कहा जाता है, जैसा कि उदाहरणों में दिखाया गया है। हालाँकि, यदि एक अशक्त वस्तु को उसके मूल Nullable <> फ़ॉर्म में शेष रहने के बजाय किसी अन्य प्रकार (जैसे ऑब्जेक्ट, आदि) के लिए बॉक्स किया जाता है, तो यह विधि मज़बूती से काम नहीं करेगी। यदि इस पद्धति को कॉल करने वाला कोड मूल, अनबॉक्स्ड ऑब्जेक्ट संदर्भ या सटीक प्रतिलिपि का उपयोग नहीं कर रहा है, तो यह इस पद्धति का उपयोग करके ऑब्जेक्ट की अशक्तता को मज़बूती से निर्धारित नहीं कर सकता है।
अधिकांश कोडिंग परिदृश्यों में, अशक्तता निर्धारित करने के लिए किसी को मूल वस्तु के प्रकार के परीक्षण पर निर्भर होना चाहिए, न कि उसका संदर्भ (उदाहरण के लिए, कोड में ऑब्जेक्ट की मूल प्रकार तक पहुंच होनी चाहिए)। इन अधिक सामान्य मामलों में, IsTypeNullable (लिंक देखें) अशक्तता का निर्धारण करने का एक विश्वसनीय तरीका है।
पुनश्च - "अशक्तता" के बारे में
मुझे एक अलग पोस्ट में किए गए अशक्तता के बारे में एक बयान दोहराना चाहिए, जो इस विषय को ठीक से संबोधित करने के लिए सीधे लागू होता है। यही है, मेरा मानना है कि यहां चर्चा का फोकस यह नहीं होना चाहिए कि यह देखने के लिए कैसे जांचा जाए कि कोई वस्तु एक सामान्य अशक्त प्रकार है, बल्कि यह भी कि क्या कोई अपने प्रकार की वस्तु के लिए अशक्त का मान प्रदान कर सकता है। दूसरे शब्दों में, मुझे लगता है कि हमें यह निर्धारित करना चाहिए कि क्या वस्तु प्रकार अशक्त है, न कि यह अशक्त है। अंतर शब्दार्थ में है, अर्थात् अशक्तता को निर्धारित करने के लिए व्यावहारिक कारण, जो आमतौर पर सभी मामलों में होता है।
रन-टाइम (वेब सेवाओं, रिमोट कॉल, डेटाबेस, फीड इत्यादि) तक संभवतः अज्ञात प्रकार की वस्तुओं का उपयोग करने वाली प्रणाली में, एक सामान्य आवश्यकता यह निर्धारित करने के लिए है कि क्या नल को ऑब्जेक्ट को सौंपा जा सकता है, या क्या ऑब्जेक्ट में शामिल हो सकता है एक अशक्त। गैर-अशक्त प्रकारों पर इस तरह के ऑपरेशनों को निष्पादित करने से आमतौर पर अपवाद उत्पन्न होंगे, जो प्रदर्शन और कोडिंग आवश्यकताओं के संदर्भ में बहुत महंगे हैं। इस तरह की समस्याओं से बचने के लिए अत्यधिक पसंदीदा दृष्टिकोण लेने के लिए, यह निर्धारित करना आवश्यक है कि क्या एक मनमाना प्रकार का एक ऑब्जेक्ट अशक्त होने में सक्षम है; यानी, चाहे वह आम तौर पर 'अशक्त' हो।
एक बहुत ही व्यावहारिक और विशिष्ट अर्थ में, .NET की शर्तों में अशक्तता बिल्कुल नहीं है कि किसी वस्तु का प्रकार अशक्त का एक प्रकार है। वास्तव में कई मामलों में, वस्तुओं में संदर्भ प्रकार होते हैं, इसमें एक अशक्त मूल्य हो सकता है, और इस तरह सभी अशक्त होते हैं; इनमें से कोई भी अशक्त प्रकार का नहीं है। इसलिए, अधिकांश परिदृश्यों में व्यावहारिक उद्देश्यों के लिए, अशक्तता की सामान्य अवधारणा के लिए परीक्षण किया जाना चाहिए, बनाम अशक्त की कार्यान्वयन-निर्भर अवधारणा। इसलिए हमें केवल .NET Nullable प्रकार पर ध्यान केंद्रित करके नहीं लटकाया जाना चाहिए, बल्कि nullability की सामान्य, व्यावहारिक अवधारणा पर ध्यान केंद्रित करने की प्रक्रिया में इसकी आवश्यकताओं और व्यवहार की हमारी समझ को शामिल करना चाहिए।