2010-11-01 3 views
28

में जेनेरिक बाधाओं का उपयोग क्यों करें मैंने सीएस में जेनेरिक के बारे में एमएसडीएन पर एक उत्कृष्ट लेख पढ़ा है।सी #

मेरे सिर में जो प्रश्न आया वह था - मुझे सामान्य बाधाओं का उपयोग क्यों करना चाहिए?

उदाहरण के लिए, अगर मैं इस तरह कोड का उपयोग करें:

public class MyClass<T> where T : ISomething 
{ 
} 

मैं ISomething साथ इस वर्ग में T के सभी संदर्भ परिवर्तन नहीं कर सकते?

इस दृष्टिकोण का उपयोग करने का क्या फायदा है?

+0

http://msdn.microsoft.com/en-us/library/d5x73970.aspx – zebrabox

उत्तर

47

आप पूछते हैं, "क्या मैं ISomething के साथ इस कक्षा में T के सभी संदर्भों को स्विच नहीं कर सकता?" तो मुझे लगता है कि आप की तुलना करने का मतलब:

public class MyClass<T> where T : ISomething 
{ 
    public T MyProperty { get; set; } 
} 

के साथ:

public class MyClass 
{ 
    public ISomething MyProperty { get; set; } 
} 

दूसरे उदाहरण में, MyProperty केवल ISomething का एक उदाहरण होने की गारंटी है। पहले उदाहरण में, MyProperty जो भी T है, भले ही यह ISomething का एक विशिष्ट उप प्रकार है।

public class MySomething : ISomething 
{ 
    public string MyOtherProperty { get; set; } 
} 

अब, अगर हम पहले, सामान्य, उदाहरण का उपयोग, हम हो सकता है:: ISomething का एक ठोस कार्यान्वयन पर विचार करें

MyClass<MySomething> myClass = new MyClass<MySomething>(); 
Console.WriteLine(myClass.MyProperty.MyOtherProperty); 

दूसरी ओर, अगर हम दूसरे उदाहरण के लिए इस्तेमाल किया है, हम क्योंकि यह केवल एक ISomething होने के लिए जाना जाता है MyOtherProperty उपयोग करने में सक्षम नहीं होगा:

MyClass myClass = new MyClass(); 
Console.WriteLine(myClass.MyProperty.MyOtherProperty); // Won't compile, no property "MyOtherProperty" 

एक अलग टिप्पणी पर, कारण इन प्रकार की कमी उपयोगी होते हैं यह है कि आप MyProperty (T टाइप करें) और ISomething के सदस्यों तक पहुंच सकते हैं।

public interface ISomething 
{ 
    public string SomeProperty { get; set; } 
} 

तो फिर तुम MyProperty.SomeProperty पहुंच सकता है: दूसरे शब्दों में, अगर ISomething की तरह घोषित किया गया। यदि आपने where T : ISomething को छोड़ दिया है तो आप SomeProperty तक पहुंचने में सक्षम नहीं होंगे क्योंकि T केवल object प्रकार के रूप में जाना जाएगा।

2

अच्छी शुरुआत के लिए, आप जेनेरिक क्लास पर जेनेरिक विधि/विधियों के लिए कोड के भीतर ISomething में परिभाषित विधियों को कॉल कर सकते हैं। अगर टी को किसी भी प्रकार की अनुमति दी गई तो यह संभव नहीं होगा (हालांकि आप हमेशा कुछ रनटाइम कास्टिंग कर सकते हैं)।

तो यह आपको टी पर क्या संकलन-समय की बाधाओं को लागू करने की अनुमति देता है और इसलिए जब आप कोड लिखते हैं - संकलन समय त्रुटियों में रनटाइम त्रुटियों को बदलते समय इन बाधाओं पर भरोसा करते हैं।

7

टाइप सुरक्षा। उदाहरण के लिए, मान लें कि आप एक कंटेनर बना रहे हैं। आप उस कंटेनर में कुछ पास कर सकते हैं और इसे कंटेनर पैरामीटर करके बाद में किसी भी प्रकार के बिना किए बिना उचित रूप में पुनर्प्राप्त कर सकते हैं। आप बस उन चीज़ों पर बाधाओं को परिभाषित कर रहे हैं जिन्हें आप अपने कंटेनर में स्टोर करना चाहते हैं।

4

यहाँ अंतर का एक उदाहरण है, बस का उपयोग कर List<>

छवि सूची सामान्य नहीं होगा द्वारा लेकिन यह सिर्फ IListElement हर जगह यह बजाय सामान्य इस्तेमाल किया प्रयोग करेंगे। अब कल्पना कीजिए कि आपके पास एक वस्तु है जो इस तरह कुछ है।

class Element : IListElement 
{ 
    public string Something { get; set; } 
} 

अब मैं सिर्फ list.Add(element); कर सकता है और वहाँ कोई वास्तविक List<Element> साथ एक अंतर नहीं होगा। लेकिन जब मैं डेटा पुनर्प्राप्त यह एक अलग कहानी है, अगर मैं सूची का उपयोग करता है IListElement तो मैं अपने डेटा वापस कास्ट करने के लिए तो मैं इसे से बाहर Something प्राप्त कर सकते हैं का उपयोग करें। इस प्रकार मुझे क्या करना होगा:

string s = ((Element)list[0]).Something; 

जबकि सामान्य के साथ मैं सिर्फ कर सकते हैं:

string s = list[0].Something; 

मुसीबत का एक बहुत बचाता है, बिल्कुल यह है कि तुलना में आगे एक सा हो जाता है, लेकिन मुझे लगता है कि आप कर सकते हैं इस से विचार प्राप्त करें।

1

हाँ आप टी के स्थान पर ISomething उपयोग कर सकते हैं, लेकिन यह होगा मैन्युअल पास एक साधारण वर्ग के लिए सामान्य प्रकार। यह अब एक सामान्य प्रकार नहीं होगा। टी का उपयोग करके आप प्रकार खुला के रूप में कई ISomething उपप्रकार के रूप में आप चाहते हैं रखने के लिए। समझौता प्रकार सुरक्षा के बिना कोड पुन: उपयोग यहां मुख्य लाभ है। उदाहरण के लिए यदि आप ISomethings का एक ढेर का उपयोग करें, आप ढेर पर किसी ISomething धक्का सकता है, लेकिन एक पॉप ISomething की वास्तविक उप-प्रकार के लिए एक खिन्न साथ होने के लिए यह उपयोगी होने के लिए है। डाउनकास्टिंग एक संभावित विफलता बिंदु बनाता है, जो सामान्य Stack<T> में नहीं होगा जहां टी: ISOMething

0

आपकी कक्षा के उपभोक्ता को दूसरों के बीच बढ़ी हुई सुरक्षा-सुरक्षा का लाभ मिलता है।

class Widget : IPokable { } 

// No generics 
Widget w = (Widget)list[0]; // cast can fail 

// With generics 
Widget w = list[0]; 
जेनरिक बिना

, अगर सूची IPokable वस्तुओं से युक्त किया गया था, कलाकारों अभी भी आवश्यक है।

कक्षा आप लागू कर रहे हैं सामान्य वस्तु पर विशिष्ट तरीकों का उपयोग कर के लाभ हो जाता है।

class PokableList<T> where T : IPokable { 
    public T PokeAndGet() { 
     currentObj.Poke(); 
     return currentObj; 
    } 
} 
0

यह यूट्यूब वीडियो वास्तव में जेनेरिक बाधाओं https://www.youtube.com/watch?v=GlqBRIgMgho के महत्व को दर्शाता है।

अब नीचे एक लंबे शाब्दिक जवाब चला जाता है।

"जेनेरिक डेटा प्रकार से तर्क को कम करने में मदद करता है। ताकि हम उच्च पुनर्प्रयोग के लिए किसी भी तर्क के साथ किसी भी डेटा प्रकार देते हैं । "

लेकिन कई बार कुछ तर्क के केवल विशिष्ट डेटा प्रकार के साथ संलग्न किया जा सकता है।

public class CompareNumeric<UNNKOWDATATYPE> 
{ 
     public bool Compareme(UNNKOWDATATYPE v1, UNNKOWDATATYPE v2) 
     { 
      if (v1 > v2) 
      {return true;} 
      else 
      {return false;} 
     } 
} 

ऊपर उदाहरण के लिए एक सरल सामान्य वर्ग अगर एक संख्या अन्य संख्या से अधिक है जो तुलना करता है। अब तुलनात्मक से अधिक और कम संख्यात्मक डेटा प्रकारों के लिए बहुत विशिष्ट है। इस तरह की तुलना स्ट्रिंग जैसे गैर-संख्यात्मक प्रकारों पर नहीं की जा सकती है।

तो अगर कुछ "int" प्रकार वाले वर्गों का उपयोग पूरी तरह से मान्य है।

CompareNumeric<int> obj = new CompareNumeric<int>(); 
bool boolgreater = obj.Compare(10,20); 

किसी को "डबल" डेटा प्रकार फिर से पूरी तरह से वैध के साथ इसे का उपयोग करता है।

CompareNumeric<double> obj = new CompareNumeric<double>(); 
bool boolgreater = obj.Compare(100.23,20.45); 

लेकिन इस तर्क के साथ स्ट्रिंग डेटा प्रकार का उपयोग अवांछनीय परिणाम का नेतृत्व करेंगे। इसलिए हम "जेनेरिक बाधाओं" का उपयोग करके हासिल की जाने वाली जेनेरिक क्लास से किस प्रकार के प्रकार संलग्न किए जा सकते हैं, इस पर बाधा डालना या बाध्य करना चाहते हैं।

CompareNumeric<string> obj = new CompareNumeric<string>(); 
bool boolgreater = obj.Compare(“interview”,”interviewer”); 

जेनेरिक प्रकार के रूप में नीचे दिए गए कोड में दिखाया गया है सामान्य वर्ग के बाद "कहाँ" कीवर्ड का उपयोग कर डेटा प्रकार को निर्दिष्ट द्वारा प्रतिबंधित किया जा सकता है। अब यदि कोई क्लाइंट निम्न श्रेणी के साथ "स्ट्रिंग" डेटा प्रकार को संलग्न करने का प्रयास करता है तो यह अवांछित परिणामों से परहेज करने की अनुमति नहीं देगा।

public class CompareNumeric<UNNKOWDATATYPE> where UNNKOWDATATYPE : int, double 
{ 

}