7

मैं एक समारोह है कि पैरामीटर के रूप में दो कार्यों लेता है के साथ काम कर रहा हूँ, और एक नया रचना एक रिटर्न:सी # कंपाइलर फ़ंक्शन हस्ताक्षर से सामान्य प्रकार के प्रतिनिधि का अनुमान क्यों नहीं लगा सकता है?

public static Action<T> Compose<T>(Action<T> first, Action second) 
{ 
    return new Action<T>(arg => 
    { 
     first(arg); 
     second(); 
    }); 
} 

मैंने देखा है कि संकलक की शिकायत करता है, तो मैं जब यह एक भेजने, T निर्दिष्ट नहीं करते स्थिर या सदस्य समारोह (के रूप में एक वास्तविक Action<T> वस्तु के खिलाफ):

static void Main(string[] args) 
{ 
    // compiler error here 
    var composed = Compose(Test,() => Console.WriteLine(" world")); 
    composed("hello"); 

    Console.ReadLine(); 
} 

public static void Test(string arg) 
{ 
    Console.Write(arg); 
} 

त्रुटि संदेश:

The arguments for method 'ConsoleTest.Program.Compose(System.Action, System.Action)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

मेरा प्रश्न: यहां टाइप तर्क का अनुमान क्यों नहीं लगाया जा सकता है? Test का हस्ताक्षर संकलन समय पर जाना जाता है, है ना? क्या वास्तव में कुछ फ़ंक्शन है जो आप Test के स्थान पर रख सकते हैं, जिससे इसके हस्ताक्षर अस्पष्ट हो जाएंगे?

पाद-टिप्पणी: मैं जानता हूँ कि मैं बस Compose करने के लिए new Action<string>(Test) बजाय Test भेज सकते हैं (जैसा कि this question में बताया गया है) - मेरे सवाल "क्यों", नहीं "कैसे मैं यह कर सकता है।"

+1

एफवाईआई - ' लिखें' इसे ठीक करता है। –

+3

यह उत्तर देखें: http://stackoverflow.com/questions/6229131/why-cant-c-sharp-infer-type-from-this-seemingly-simple-obvious-case – lukegravitt

+0

धन्यवाद @lukegravitt - शीर्ष जवाब वहां भाषा की कल्पना का संदर्भ देता है, और लिपर्ट खुद को झुकाता है। – McGarnagle

उत्तर

6

मुझे लगता है कि शायद इस तथ्य के साथ कुछ करने के लिए कुछ है कि कम से कम कंपाइलर के परिप्रेक्ष्य से Test वास्तव में एक 'विधि समूह' है जब तक कि संकलक ने यह निर्धारित नहीं किया है कि इसके किस प्रकार के पैरामीटर होंगे। यह सच है भले ही समूह में केवल एक ही विधि है (मौजूदा दायरे में केवल एक Test विधि)।

का निरीक्षण करें:

var composed = Compose<object>(Test,() => Console.WriteLine(" world")); 

त्रुटि पैदावार:

The best overloaded method match for ' Compose<object>(System.Action<object>, System.Action) ' has some invalid arguments

Argument 1: cannot convert from 'method group' to ' System.Action<object> '

लेकिन यह ठीक है:

var composed = Compose<string>(Test,() => Console.WriteLine(" world")); 

मेरा अनुमान है कि संकलक दोनों विधि समूह अभिव्यक्ति देखते हैं (Test) और स्पष्ट रूप से टाइप जेनेरिक विधि आमंत्रण (Compose) 'unb' के रूप में एक अर्थ में ound '। यह पैरामीटर के 'अनबाउंड' हस्ताक्षर से Compose पर विधि समूह से चयन करने के लिए कौन सी विधि का चयन नहीं कर सकता है, और यह निर्धारित नहीं कर सकता कि हस्ताक्षर से Compose के लिए प्रकार प्रकार पैरामीटर कौन सा है। पूरे कथन को संकलित करने के लिए इसे एक या दूसरे को 'बाध्य' होना चाहिए।

+2

ऐसा लगता है कि आप सही रास्ते पर हैं ... इन पंक्तियों के साथ और अधिक चर्चा है, यहां: http://stackoverflow.com/a/6231921/1001985 – McGarnagle

0

इसे कॉन्वर्सिस के साथ करना पड़ सकता है। हालांकि Test के तर्क का प्रकार ज्ञात है, हो सकता है कि आप एक अधिक विशिष्ट प्रकार का प्रतिनिधि बनाना चाहें।

public class BaseClass { } 
public class DerivedClass : BaseClass { } 

static class Program 
{ 
    static void Main(string[] args) 
    { 
     var composed = Compose<DerivedClass>(Test,() => Console.WriteLine(" world")); 
     composed(new DerivedClass()); 

     Console.ReadLine(); 
    } 

    public static void Test(BaseClass arg) 
    { 
     Console.Write(arg); 
    } 
} 
संबंधित मुद्दे

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