2008-10-10 14 views
69

यह इस तरह है किसी # जेनेरिक्स अनुमति नहीं दी जाएगी प्रतिनिधि प्रकार प्रतिबन्ध

class GenericCollection<T> : SomeBaseCollection<T> where T : Delegate 

मैं के लिए मुझे के जीवन इस कल रात .NET 3.5 में पूरा नहीं कर सकता है सी # में एक वर्ग को परिभाषित करना संभव है। मैं

delegate, Delegate, Action<T> and Func<T, T>

मुझे ऐसा लगता है कि इस का उपयोग कर किसी तरह से स्वीकार्य होना चाहिए की कोशिश की। मैं अपना खुद का EventQueue लागू करने की कोशिश कर रहा हूं।

मैं बस यह [आदिम अनुमानित मन] कर रहा हूं।

internal delegate void DWork(); 

class EventQueue { 
    private Queue<DWork> eventq; 
} 

लेकिन फिर मैं विभिन्न प्रकार के कार्यों के लिए एक ही परिभाषा का पुन: उपयोग करने की क्षमता खो देता हूं।

विचार?

उत्तर

64

कई वर्ग सामान्य बाधाओं के रूप में अनुपलब्ध हैं - एनम एक और है।

प्रतिनिधियों के लिए, निकटतम आप प्राप्त कर सकते हैं ": वर्ग", शायद जाँच करने के लिए प्रतिबिंब का उपयोग (उदाहरण के लिए, स्थिर निर्माता में) है कि टी एक प्रतिनिधि है:

static GenericCollection() 
{ 
    if (!typeof(T).IsSubclassOf(typeof(Delegate))) 
    { 
     throw new InvalidOperationException(typeof(T).Name + " is not a delegate type"); 
    } 
} 
+7

+1: 1) स्थिर कन्स्ट्रक्टर का उपयोग करके और 2) प्रकार के प्रारंभिक अजीब डीबगिंग स्थितियों के कारण विस्तृत संदेश सहित। –

+6

@MarcGravell: एक स्थिर प्रारंभकर्ता में एक अपवाद फेंक नहीं है का उल्लंघन 'CA1065: अप्रत्याशित locations' में अपवाद न बढ़ाएं ... मैं हमेशा इस धारणा है कि आप एक कस्टम कोड विश्लेषण नियम का उपयोग करना चाहिए की अवैध प्रयोगों को खोजने के लिए था, आपके कक्षा जो आम तौर पर रन-टाइम पर उपलब्ध नहीं होती है। –

13

संपादित करें : कुछ प्रस्तावित कार्य arounds इन लेखों में प्रस्तावित हैं:

http://jacobcarpenters.blogspot.com/2006/06/c-30-and-delegate-conversion.html

http://jacobcarpenters.blogspot.com/2006_11_01_archive.html


C# 2.0 specification हम पढ़ सकते हैं से (20.7, प्रतिबन्ध):

एक वर्ग प्रकार बाधा निम्नलिखित नियमों को पूरा करना चाहिए:

  • प्रकार एक वर्ग प्रकार होना चाहिए।
  • प्रकार को सील नहीं किया जाना चाहिए। System.Array, System.Delegate, System.Enum, या System.ValueType:
  • प्रकार निम्नलिखित प्रकारों में से एक नहीं होना चाहिए।
  • प्रकार वस्तु नहीं होना चाहिए। चूंकि ऑब्जेक्ट से सभी प्रकार प्राप्त होते हैं, इसलिए इस तरह की बाधा का कोई प्रभाव नहीं पड़ता अगर इसकी अनुमति थी।
  • किसी दिए गए प्रकार पैरामीटर के लिए सबसे अधिक बाधा एक वर्ग प्रकार हो सकती है।

    error CS0702: Constraint cannot be special class 'System.Delegate' 
    

    की जानकारी और इस मुद्दे पर जांच के लिए पढ़ा here:

और यकीन है कि पर्याप्त VS2008 एक त्रुटि बाहर थूक।

3

प्रतिनिधि पहले ही चेनिंग का समर्थन करता है। क्या यह आपकी आवश्यकताओं को पूरा नहीं करता है?

public class EventQueueTests 
{ 
    public void Test1() 
    { 
     Action myAction =() => Console.WriteLine("foo"); 
     myAction +=() => Console.WriteLine("bar"); 

     myAction(); 
     //foo 
     //bar 
    } 

    public void Test2() 
    { 
     Action<int> myAction = x => Console.WriteLine("foo {0}", x); 
     myAction += x => Console.WriteLine("bar {0}", x); 
     myAction(3); 
     //foo 3 
     //bar 3 
    } 

    public void Test3() 
    { 
     Func<int, int> myFunc = x => { Console.WriteLine("foo {0}", x); return x + 2; }; 
     myFunc += x => { Console.WriteLine("bar {0}", x); return x + 1; }; 
     int y = myFunc(3); 
     Console.WriteLine(y); 

     //foo 3 
     //bar 3 
     //4 
    } 

    public void Test4() 
    { 
     Func<int, int> myFunc = x => { Console.WriteLine("foo {0}", x); return x + 2; }; 
     Func<int, int> myNextFunc = x => { x = myFunc(x); Console.WriteLine("bar {0}", x); return x + 1; }; 
     int y = myNextFunc(3); 
     Console.WriteLine(y); 

     //foo 3 
     //bar 5 
     //6 
    } 

} 
+0

thats नहीं वास्तव में कार्यक्षमता मैं के लिए ... मैं अपने सामान्य वर्ग पर एक प्रकार बाधा बनाने के लिए कोशिश कर रहा था देख रहा हूँ ... –

3

मैं एक स्थिति है जहाँ मैं आंतरिक रूप से एक Delegate से निपटने के लिए की जरूरत भर में आया था, लेकिन मैं एक सामान्य बाधा चाहता था। विशेष रूप से, मैं प्रतिबिंब का उपयोग करके एक ईवेंट हैंडलर जोड़ना चाहता था, लेकिन मैं प्रतिनिधि के लिए एक सामान्य तर्क का उपयोग करना चाहता था। नीचे दिए गए कोड काम नहीं करता है, क्योंकि "हैंडलर" एक प्रकार चर रहा है, और संकलक डाली नहीं होगा HandlerDelegate रहे हैं:

public void AddHandler<Handler>(Control c, string eventName, Handler d) { 
    c.GetType().GetEvent(eventName).AddEventHandler(c, (Delegate) d); 
} 

हालांकि, अगर आप एक समारोह है कि आप के लिए रूपांतरण करता है पारित कर सकते हैं। convert एक Handler तर्क लेता है और एक Delegate रिटर्न:

public void AddHandler<Handler>(Control c, string eventName, 
        Func<Delegate, Handler> convert, Handler d) { 
     c.GetType().GetEvent(eventName).AddEventHandler(c, convert(d)); 
} 

अब संकलक खुश है। विधि को कॉल करना आसान है। उदाहरण के लिए, एक विंडोज पर KeyPress घटना के लिए संलग्न नियंत्रण फॉर्म्स:

AddHandler<KeyEventHandler>(someControl, 
      "KeyPress", 
      (h) => (KeyEventHandler) h, 
      SomeControl_KeyPress); 

जहां SomeControl_KeyPress घटना लक्ष्य है। कुंजी कनवर्टर लैम्ब्डा है - यह कोई काम नहीं करता है, लेकिन यह संकलक को विश्वास दिलाता है कि आपने इसे एक वैध प्रतिनिधि दिया है।

(280Z28 शुरू करें) @ जस्टिन: इसका उपयोग क्यों नहीं करें?

public void AddHandler<Handler>(Control c, string eventName, Handler d) { 
    c.GetType().GetEvent(eventName).AddEventHandler(c, d as Delegate); 
} 

(अंत 280Z28)

+1

@Justin: मैं अंत में मेरी टिप्पणी डालने के लिए अपने जवाब संपादित के बाद से यह एक है कोड ब्लॉक –

+1

अच्छी पकड़। यह बहुत अच्छी तरह से काम करता है। –

10

आप एक आईएल वीवर पर एक संकलन समय निर्भरता आप Fody साथ ऐसा कर सकते लेने के लिए तैयार हैं।

Fody को https://github.com/Fody/ExtraConstraints

आपका कोड इस

public class Sample 
{ 
    public void MethodWithDelegateConstraint<[DelegateConstraint] T>() 
    {   
    } 
    public void MethodWithEnumConstraint<[EnumConstraint] T>() 
    { 
    } 
} 

की तरह लग सकता है और जैसा कि ऊपर उल्लेख इस

public class Sample 
{ 
    public void MethodWithDelegateConstraint<T>() where T: Delegate 
    { 
    } 

    public void MethodWithEnumConstraint<T>() where T: struct, Enum 
    { 
    } 
} 
+0

टूटी लिंक। क्या आपके पास वर्तमान है? –

+0

@JustinMorgan अद्यतन – Simon

2

को संकलित किया जा इस ऐड का उपयोग करना, आप नहीं हो सकता एक सामान्य बाधा के रूप में प्रतिनिधियों और Enum। System.Object और System.ValueType भी सामान्य बाधा के रूप में उपयोग नहीं किया जा सकता है।

यदि आप आईएल में उचित कॉल करते हैं तो आसपास का काम हो सकता है। यह ठीक काम करेगा।

जॉन स्कीट द्वारा यहां एक अच्छा उदाहरण है।

http://code.google.com/p/unconstrained-melody/

मैं विभाग 3 संस्करण में से जॉन स्कीट किताब सी # मेरी संदर्भ ले लिया है।

1
MSDN

कंपाइलर त्रुटि CS0702 के अनुसार

बाधा नहीं किया जा सकता विशेष वर्ग 'पहचानकर्ता' निम्नलिखित प्रकार की कमी के रूप में नहीं किया जा सकता है:

  • प्रणाली।वस्तु
  • System.Array
  • System.Delegate
  • System.Enum
  • System.ValueType।