2009-02-12 8 views
7

मैं एक तरह से स्वचालित रूप से एक कार्य या समारोह और सबसे अच्छा मैं के साथ आ सकते हैं के लिए कुछ कास्ट करने के लिए यह पता लगाने की कोशिश कर रहा हूँ कुछ इस तरह है:मैं स्पष्ट रूप से एक्सटेंशन विधियों के साथ प्रतिनिधि क्यों नहीं डाल सकता?

[TestFixture] 
public class ExecutionTest 
{ 
    public void BadMethod() 
    { 
     throw new Exception("Something bad happened"); 
    } 

    [Test] 
    public void TestBadMethod() 
    { 
     // Want this, but it won't work!! 
     // BadMethod.Execute().IgnoreExceptions(); 

     // Ick 
     ((Action)BadMethod).Exec().IgnoreExceptions(); 

     // Still ick 
     ((Action)BadMethod).IgnoreExceptions(); 

     // Do not want 
     ExtensionMethods.Exec(BadMethod).IgnoreExceptions(); 

     // Better but still meh 
     this.Exec(BadMethod).IgnoreExceptions(); 

    } 
} 

public static class ExtensionMethods 
{ 
    public static Action Exec(this Action action) 
    { return action; } 

    public static Action Exec(this object obj, Action action) 
    { return action; } 

    public static void IgnoreExceptions(this Action action) 
    { 
     try { action(); } 
     catch {} 
    } 
} 

एक बेहतर/आसान करने के लिए जिस तरह से करने के लिए है यह, कोई विचार?

उत्तर

5

सी # में, जब आप बिना किसी कंस्ट्रैसिस के विधि नाम का उपयोग करते हैं, तो इसे विधि समूह कहा जाता है और इसमें संकलन समय के अलावा कोई प्रतिनिधित्व नहीं होता है। एक विधि समूह एक से अधिक तरीकों का प्रतिनिधित्व कर सकता है (ओवरलोड और ओवरराइड की वजह से), इसलिए यह स्पष्ट रूप से पहचानने के लिए कि किस विधि की आवश्यकता है, एक लक्षित प्रतिनिधि प्रकार प्रदान किया जाना चाहिए।

आपके मामले में, आप सोच रहे हैं कि एक्सटेंशन विधि पैरामीटर प्रकार फ़ंक्शन के समाधान को ट्रिगर नहीं करेगा। सीधे शब्दों में कहें, प्रकार का मूल्यांकन करने के बाद एक्सटेंशन का मूल्यांकन किया जाता है, यानी, यह पैरामीटर एक निहित रूपांतरण लक्ष्य के रूप में उपयोग नहीं किया जा सकता है।

कारण है कि यह टूट जाएगा का उदाहरण:

class Test 
{ 
    void M (void) // Fits Action delegate 
    { 
    } 

    int M (int) // Fits Func<int,int> delegate 
    { 
     return 5; 
    } 

    void Test() 
    { 
     M.Exec(); // UHOH!!! Which Exec to resolve to ??? 
    } 
} 


public static class Extensions 
{ 
    public static void Exec(this Action action) { } 
    public static void Exec(this Func<int, int> func) { } 
} 

जैसा कि आप देख सकते हैं, वहाँ एक संघर्ष है, लेकिन तथ्य की बात के रूप में, संघर्ष कभी नहीं होता है क्योंकि सी # यहाँ तक कि एक मिलान खोजने की कोशिश नहीं करेंगे एक विधि समूह के साथ विस्तार।

नोट यह कैसे या तो काम नहीं करेगा:

class A 
{ 
    public static implicit operator int (A a) 
    { 
     return 5; 
    } 

    void F() 
    { 
     A a = new A(); 
     a.Blah(); // Error! It won't implicitly try C.Blah() 
    } 
} 

public static class C 
{ 
    public static void Blah (int i) 
    { 
    } 
} 

सी # C.Blah(int) करने के लिए A से मेल नहीं खाएगी, क्योंकि यह एक अंतर्निहित रूपांतरण की आवश्यकता होगी।

+0

यह सुनिश्चित नहीं है कि यह विधि ओवरलोड का मुद्दा है क्योंकि संकलक यह पता लगाएगा कि कौन से कॉल करना है। लेकिन यह अब तक का सबसे अच्छा जवाब है जिसे मैंने देखा है ... –

2

सिक्काकोइन के अनुसार, यह विधि अधिभार के लिए अति उत्साही प्यार की वजह से सी # में अच्छी तरह से काम नहीं करेगा। केवल वैकल्पिक हल मैंने देखा लोगों के बाद उसे उपयोग कार्रवाई और समारोह के तरीकों बनाने के लिए है:

public Action Action(Action f) { return f; } 
public Action<A> Action<A>(Action<A> f) { return f; } 
... 
public Func<A,B,C,D,E> Func(Func<A,B,C,D,E> f) { return f; } 

तुम भी उन सब को 'एफ' लघु वाक्य रचना के कुछ प्रकार प्राप्त करने के लिए कह सकते हैं:

F(BadMethod).NoExceptions(); 

आप हो सकता है इन वर्गों को अपनी कक्षा में परिभाषित न करने का निर्णय लें, और उन्हें एक Funcs उपयोगिता या कुछ में डाल दें। उर्फ यह एफ के साथ है और यह अंत नहीं है बहुत बुरा:

F.F(BadMethod).NoException(); 

लेकिन कुल मिलाकर यह अभी भी :(बेकार

+0

हाँ, यही कारण है कि मेरे पास था (इस ऑब्जेक्ट ऑब्जेक्ट, एक्शन एक्शन) के लिए एक्सटेंशन विधि, इसलिए यह किसी भी वर्ग के अंदर यह कॉल करके काम करेगी। एक्शन() या यह। फनक() –

+0

क्षमा करें, मुझे टी नहीं देखा वह निष्पादन परिभाषा - कुछ हद तक भ्रामक नाम, नहीं: पी – MichaelGG

+0

हाँ, मैंने इसे अपने वास्तविक कोड में बदल दिया। उस समय यह "धाराप्रवाह" लग रहा था। –

1

एफ # आप एक बेहतर प्रकार निष्कर्ष प्रदान करके बहुत स्वाभाविक रूप से बात इस तरह का काम करने दिया। सिस्टम

संबंधित मुद्दे