दिलचस्प पोस्ट
एक DataTable में एन डेटाटैबल्स का संयोजन एक std :: vector के इटरेटर के सूचकांक को प्राप्त करने का सबसे प्रभावी तरीका क्या है? आयन-सामग्री और आयन-पाद लेख के पास अलग-अलग $ का दायरा है मैं एक निर्देशिका का पूंजीकरण बदलता हूं और गिट उस पर उठने नहीं लगता कैसे जानूं कि मेरा ऐप कब मार गया है? एक दृश्य की पृष्ठभूमि में एक अर्धवृत्त बनाएं क्या संकेतक का आकार डेटा और फ़ंक्शन पॉइंटर्स के बीच भिन्न हो सकता है? जावा में किसी पाठ फ़ाइल से एक विशिष्ट पंक्ति पढ़ना Ctypes के लिए रनटाइम पर LD_LIBRARY_PATH बदलना क्यों ValueType.GetHashCode () लागू की तरह है? क्यों नहीं java.util.Set मिलता है (int सूचकांक)? जावास्क्रिप्ट में उपज कीवर्ड क्या है? MouseUp और MouseDown घटनाओं के साथ एक क्लिक अनुकरण या अन्यथा का सबसे अच्छा तरीका क्या है? आप पायथन में एकाधिक मान कैसे वापस करते हैं? mylib.so पाठ पुनर्स्थापना है यह स्मृति बर्बाद कर रहा है और एक सुरक्षा जोखिम है। कृपया ठीक करें

सामान्य एक्सटेंशन विधि के साथ कोई प्रकार का अनुमान नहीं

मेरे पास निम्नलिखित विधि है:

public static TEventInvocatorParameters Until <TEventInvocatorParameters, TEventArgs>(this TEventInvocatorParameters p, Func<TEventArgs, bool> breakCond) where TEventInvocatorParameters : EventInvocatorParameters<TEventArgs> where TEventArgs : EventArgs { p.BreakCondition = breakCond; return p; } 

और यह वर्ग

 public class EventInvocatorParameters<T> where T : EventArgs { public Func<T, bool> BreakCondition { get; set; } // Other properties used below omitted for brevity. } 

अब, मेरे पास निम्न समस्याएं हैं:

  1. यह एक्सटेंशन विधि सभी प्रकारों पर दिखाती है, यहां तक ​​कि string भी।
  2. मैं new EventInvocatorParameters<EventArgs>(EventABC).Until(e => false); नहीं लिख सकता। new EventInvocatorParameters<EventArgs>(EventABC).Until(e => false); यह मुझे बता रहा है "विधि के लिए प्रकार तर्क … उपयोग से अनुमानित नहीं किया जा सकता है।"

क्या मैं इस तरह सामान्य प्रकार पैरामीटर का उपयोग नहीं कर सकता? आप इस समस्या का समाधान कैसे करेंगे?
महत्वपूर्ण बिंदु: मुझे उन जेनेरिक मापदंडों की आवश्यकता है, क्योंकि मुझे उसी प्रकार वापस जाने की ज़रूरत है जिस पर इस विस्तार विधि को बुलाया गया था।


विस्तृत चित्र (प्रश्न का उत्तर देने के लिए आवश्यक नहीं है!):
मैं घटनाओं का आह्वान करने के लिए एक धाराप्रवाह इंटरफ़ेस बनाने का प्रयास कर रहा हूं। आधार यह स्थिर वर्ग है:

 public static class Fire { public static void Event<TEventArgs>( ConfiguredEventInvocatorParameters<TEventArgs> parameters) where TEventArgs : EventArgs { if (parameters.EventHandler == null) { return; } var sender = parameters.Sender; var eventArgs = parameters.EventArgs; var breakCondition = parameters.BreakCondition; foreach (EventHandler<TEventArgs> @delegate in parameters.EventHandler.GetInvocationList()) { try { @delegate(sender, eventArgs); if (breakCondition(eventArgs)) { break; } } catch (Exception e) { var exceptionHandler = parameters.ExceptionHandler; if (!exceptionHandler(e)) { throw; } } } } } 

यह विधि सुनिश्चित करने के लिए केवल पूरी तरह से कॉन्फ़िगर पैरामीटर के साथ कॉल किया जा सकता है, यह केवल एक ConfiguredEventInvocatorParameters<T> स्वीकार करता है ConfiguredEventInvocatorParameters<T> जो EventInvocatorParameters<T> से प्राप्त EventInvocatorParameters<T> :

 public class ConfiguredEventInvocatorParameters<T> : EventInvocatorParameters<T> where T : EventArgs { public ConfiguredEventInvocatorParameters( EventInvocatorParameters<T> parameters, object sender, T eventArgs) : base(parameters) { EventArgs = eventArgs; Sender = sender; } public T EventArgs { get; private set; } public object Sender { get; private set; } } 

निम्नलिखित वैध कॉल होंगे:

 Fire.Event(EventName.With(sender, eventArgs)); Fire.Event(EventName.With(sender, eventArgs).Until(e => e.Cancel)); Fire.Event(EventName.Until(e => e.Cancel).With(sender, eventArgs)); 

निम्न अवैध होगा:

 // no sender or eventArgs have been specified, ie missing call to With(...) Fire.Event(EventName.Until(e => e.Cancel)); 

इस कार्य को बनाने के लिए, इसके With नामित एक्स्टेंशन विधियों मौजूद हैं, जो एक TEventInvocatorParameters EventHandler<TEventArgs या एक TEventInvocatorParameters स्वीकार करते हैं और एक ConfiguredEventInvocatorParameters<TEventArgs> साथ में आने वाली सभी कॉल्स अब भी ConfiguredEventInvocatorParameters<TEventArgs> वापस करने की आवश्यकता है, अन्यथा वैध कॉल का दूसरा उदाहरण (अंत Until साथ) काम नहीं करेगा
अगर सामान्य में एपीआई पर आपका कोई विचार है, तो कृपया मुझे बताएं हालांकि, मैं निम्नलिखित तीन चीजों से बचना चाहता हूं:

  • केवल रनटाइम पर असफल होने पर पैरामीटर पूरी तरह से कॉन्फ़िगर नहीं किए गए हैं
  • EventName.With(...).Until(...).Fire() तरह एक व्युत्क्रम सिंटैक्स बना रहा है EventName.With(...).Until(...).Fire()
  • चीजों को शुरू करने के लिए कुख्यात विधि का प्रयोग करें: Fire(EventName).With(...).Until(...).Do();

वेब के समाधान से एकत्रित समाधान "सामान्य एक्सटेंशन विधि के साथ कोई प्रकार का अनुमान नहीं"

जेनेरिक विधि प्रकार का अनुमान जानबूझकर बाधाओं से कोई कटौती नहीं करता है। बल्कि, कटौती तर्कों और औपचारिक मापदंडों से की जाती है , और फिर बाधाओं के खिलाफ अनुमानित तर्कों की जाँच की जाती है

बाधाओं और विधि के हस्ताक्षर के कुछ डिजाइन मुद्दों पर विस्तृत चर्चा के लिए, कई दर्जन लोगों सहित, मुझे यह कहते हुए गलत है कि मौजूदा डिजाइन समझदार है, इस विषय पर मेरा आलेख देखें:

http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx

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

 public abstract class EventInvocatorParametersBase <TEventInvocatorParameters, TEventArgs> where TEventArgs : EventArgs where TEventInvocatorParameters : EventInvocatorParametersBase<TEventInvocatorParameters, TEventArgs> { protected EventInvocatorParametersBase( EventHandler<TEventArgs> eventHandler, Func<Exception, bool> exceptionHandler, Func<TEventArgs, bool> breakCondition) { EventHandler = eventHandler; ExceptionHandler = exceptionHandler; BreakCondition = breakCondition; } protected EventInvocatorParametersBase( EventHandler<TEventArgs> eventHandler) : this(eventHandler, e => false, e => false) { } public Func<TEventArgs, bool> BreakCondition { get; set; } public EventHandler<TEventArgs> EventHandler { get; set; } public Func<Exception, bool> ExceptionHandler { get; set; } public TEventInvocatorParameters Until( Func<TEventArgs, bool> breakCondition) { BreakCondition = breakCondition; return (TEventInvocatorParameters)this; } public TEventInvocatorParameters WithExceptionHandler( Func<Exception, bool> exceptionHandler) { ExceptionHandler = exceptionHandler; return (TEventInvocatorParameters)this; } public ConfiguredEventInvocatorParameters<TEventArgs> With( object sender, TEventArgs eventArgs) { return new ConfiguredEventInvocatorParameters<TEventArgs>( EventHandler, ExceptionHandler, BreakCondition, sender, eventArgs); } } public class EventInvocatorParameters<T> : EventInvocatorParametersBase<EventInvocatorParameters<T>, T> where T : EventArgs { public EventInvocatorParameters(EventHandler<T> eventHandler) : base(eventHandler) { } } public class ConfiguredEventInvocatorParameters<T> : EventInvocatorParametersBase<ConfiguredEventInvocatorParameters<T>, T> where T : EventArgs { public ConfiguredEventInvocatorParameters( EventHandler<T> eventHandler, Func<Exception, bool> exceptionHandler, Func<T, bool> breakCondition, object sender, T eventArgs) : base(eventHandler, exceptionHandler, breakCondition) { EventArgs = eventArgs; Sender = sender; } public ConfiguredEventInvocatorParameters(EventHandler<T> eventHandler, object sender, T eventArgs) : this(eventHandler, e => false, e => false, sender, eventArgs) { } public T EventArgs { get; private set; } public object Sender { get; private set; } } public static class EventExtensions { public static EventInvocatorParameters<TEventArgs> Until<TEventArgs>( this EventHandler<TEventArgs> eventHandler, Func<TEventArgs, bool> breakCondition) where TEventArgs : EventArgs { return new EventInvocatorParameters<TEventArgs>(eventHandler). Until(breakCondition); } public static EventInvocatorParameters<TEventArgs> WithExceptionHandler<TEventArgs>( this EventHandler<TEventArgs> eventHandler, Func<Exception, bool> exceptionHandler) where TEventArgs : EventArgs { return new EventInvocatorParameters<TEventArgs>(eventHandler). WithExceptionHandler(exceptionHandler); } public static ConfiguredEventInvocatorParameters<TEventArgs> With<TEventArgs>( this EventHandler<TEventArgs> eventHandler, object sender, TEventArgs eventArgs) where TEventArgs : EventArgs { return new ConfiguredEventInvocatorParameters<TEventArgs>( eventHandler, sender, eventArgs); } } 

यह आपको इस तरह से कोड लिखने की अनुमति देता है:

 Fire.Event(EventName.WithExceptionHandler(e => false) .Until(e => false).With(this, EventArgs.Empty)); Fire.Event(EventName.With(this, EventArgs.Empty)); Fire.Event(EventName.WithExceptionHandler(e => false) .With(this, EventArgs.Empty).Until(e => false)); Fire.Event(EventName.With(this, EventArgs.Empty) .WithExceptionHandler(e => false).Until(e => false)); 

लेकिन यह आपको यह लिखने की अनुमति नहीं देता है, क्योंकि सभी आवश्यक जानकारी (इवेंटएआरजीएस और प्रेषक) प्रदान नहीं किए गए हैं:

 Fire.Event(EventName.Until(e => false)); Fire.Event(EventName); 

क्या कोई कारण है कि आपको विस्तार विधि का उपयोग करने की आवश्यकता है? यदि आप EventInvocatorParameters<T> वर्ग Until डालते हैं, तो आप दोनों समस्याओं से बच सकते हैं:

 public class EventInvocatorParameters<T> where T : EventArgs { public Func<T, bool> BreakCondition { get; set; } // Other properties used below omitted for brevity. public EventInvocatorParameters<T> Until (Func<T, bool> breakCond) { this.BreakCondition = breakCond; return this; } } 

मुझे पता है कि एक पुलिस-आउट का बिट, लेकिन क्या आपने आरएसी के बजाय उपयोग करने पर विचार किया है, जो कि आप क्या करने की कोशिश करते हुए फिर से खोजना चाहते हैं?