यहां एक व्यावहारिक उदाहरण है कि आप अतिरिक्त कन्स्ट्रक्टर प्रकार पैरामीटर और वर्कअराउंड कैसे प्राप्त करना चाहते हैं।
मैं IDisposable
के लिए एक सरल RefCounted
आवरण लागू करने के लिए जा रहा हूँ:
public class RefCounted<T> where T : IDisposable
{
public RefCounted(T value)
{
innerValue = value;
refCount = 1;
}
public void AddRef()
{
Interlocked.Increment(ref refCount);
}
public void Dispose()
{
if(InterlockedDecrement(ref refCount)<=0)
innerValue.Dispose();
}
private int refCount;
private readonly innerValue;
}
यह ठीक हो रहा है। लेकिन जल्दी या बाद में आप RefCounted<Control>
से RefCounted<Button>
पर डालना चाहते हैं, जबकि ऑब्जेक्ट रेफरेंस गिनती दोनों रखें, यानी केवल तभी जब दोनों उदाहरण अंतर्निहित ऑब्जेक्ट को निपटाने के लिए निपटाए जा रहे हों।
सबसे अच्छा तरीका है अगर आप लिख सकते हैं (जैसे सी ++ लोग क्या कर सकते हैं)
public RefCounted(RefCounted<U> other)
{
...whatever...
}
लेकिन सी # इस अनुमति नहीं देता है। तो समाधान कुछ संकेतों का उपयोग किया जाता है।
private readonly Func<T> valueProvider;
private readonly Action disposer;
private RefCounted(Func<T> value_provider, Action disposer)
{
this.valueProvider = value_provider;
this.disposer = disposer;
}
public RefCounted(T value) : this(() => value, value.Dispose)
{
}
public RefCounted<U> Cast<U>() where U : T
{
AddRef();
return new RefCounted<U>(() => (U)(valueProvider()),this.Dispose);
}
public void Dispose(){
if(InterlockedDecrement(ref refCount)<=0)
disposer();
}
यदि आपकी कक्षा में सामान्य प्रकार के कोई फ़ील्ड हैं, तो आपके पास उन सभी प्रकारों को कक्षा में रखने के अलावा कोई विकल्प नहीं है। हालांकि, अगर आप केवल कन्स्ट्रक्टर से कुछ प्रकार छिपाना चाहते हैं, तो आपको उपर्युक्त चाल का उपयोग करना होगा - एक सबकुछ एक साथ रखने के लिए एक छुपा कन्स्ट्रक्टर होना, और उस कन्स्ट्रक्टर को कॉल करने के लिए सामान्य जेनेरिक फ़ंक्शन को परिभाषित करना होगा।
स्रोत
2014-07-24 02:44:19
आप एक ही नाम के साथ एक सामान्य और गैर-जेनेरिक वर्ग की अनुमति नहीं देकर समान नाम वाली कक्षा की समस्या के आसपास हो सकते हैं (गंभीरता से, सी # यह अनुमति देता है?)। सामान्य वर्ग के सामान्य निर्माता के लिए, मुझे नहीं लगता कि यह बहुत ही घृणित है - यह केवल उच्च आदेश सामान्यता है। –
एक टिप्पणी - सामान्य वर्ग में कन्स्ट्रक्टर सामान्य है, क्योंकि कक्षा सामान्य है। हालांकि (आपका उत्तर लेना) यह ** अतिरिक्त ** जेनेरिक तर्क निर्दिष्ट नहीं कर सकता है। बहुत अच्छे उदाहरणों के लिए धन्यवाद! – greenoldman
@ पीटर: नहीं, समान नामित वर्ग समस्या कोई समस्या नहीं है, क्योंकि यद्यपि आप * टाइप * एआरटी टाइप करके कक्षाओं को "ओवरलोड" कर सकते हैं, वहां कोई अस्पष्टता नहीं है। इसके उदाहरण के लिए 'टुपल' देखें। –