2010-05-14 12 views
5

Func object बनाना संभव है जो सामान्य विधि का संदर्भ देता है? LINQ OrderBy की तरह:सी #: जेनेरिक तरीकों के लिए Func <T, TResult>

public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
    this IEnumerable<TSource> source, 
    Func<TSource, TKey> keySelector 
) 
+0

क्या आप इसका नमूना पोस्ट कर सकते हैं कि आप इसका उपयोग कैसे करना चाहते हैं? मुझे लगता है कि यह बिल्कुल स्पष्ट नहीं है कि आप वर्णन से क्या हासिल करना चाहते हैं। – eglasius

उत्तर

19

यदि मैं आपको सही ढंग से समझता हूं, तो आप पूछ रहे हैं कि क्या आप एक अज्ञात विधि से किसी सामान्य विधि का संदर्भ दे सकते हैं या नहीं।

उत्तर हाँ है।

उदाहरण के लिए, मान लीजिए कि आप कुछ Func चाहते हैं जो सॉर्ट किए गए क्रम में IEnumerable<int> ऑब्जेक्ट के तत्व लौटाता है (ठीक है OrderBy<int, int>)। आप ऐसा कर सकता है:

Func<IEnumerable<int>, Func<int, int>, IOrderedEnumerable<int>> orderByFunc = 
    System.Linq.Enumerable.OrderBy<int, int>; 

तो फिर तुम बस की तरह इस Func इस्तेमाल कर सकते हैं किसी भी अन्य:

int[] ints = new int[] { 1, 3, 5, 4, 7, 2, 6, 9, 8 }; 

// here you're really calling OrderBy<int, int> -- 
// you've just stored its address in a variable of type Func<...> 
foreach (int i in orderByFunc(ints, x => x)) 
    Console.WriteLine(i); 

आउटपुट:

1 
2 
3 
4 
5 
6 
7 
8 
9 

दूसरी ओर, यदि आप पूछ रहे हैं कि क्या इस तरह की "जेनेरिक अनाम विधि" बनाना संभव है:

Func<T> getDefault<T> =() => default(T); 

फिर यह आपके संदर्भ पर निर्भर करता है। यह एक संदर्भ के भीतर से किया जा सकता है जहां T पहले से ही सामान्य प्रकार के पैरामीटर के रूप में घोषित किया जाता है - अर्थात्, सामान्य वर्ग या जेनेरिक विधि के भीतर। (फ्रेडी रियोस के जवाब देखें।) इस तरह के एक संदर्भ के बाहर, दुर्भाग्य से, यह अवैध है।

+1

धन्यवाद दान! अच्छा जवाब +1। आपका मतलब है कि एक सामान्य 'Func' ऑब्जेक्ट को परिभाषित करना संभव नहीं है? : ओ – SDReyes

+2

@SDReyes: यह इस बात पर निर्भर करता है कि आपके पास 'टी' है जो आपके दायरे में परिभाषित है। यही है, यदि आप एक सामान्य वर्ग के भीतर काम कर रहे हैं, उदाहरण के लिए, तो उस कक्षा में किसी विधि के भीतर आप 'Func ' घोषित कर सकते हैं। आप इसे एक सामान्य विधि के भीतर भी कर सकते हैं। लेकिन एक संदर्भ में एक सामान्य अज्ञात विधि घोषित करने के लिए जो पहले से ही सामान्य नहीं है (यानी, किसी गैर-जेनेरिक वर्ग से संबंधित किसी भी सादे वेनिला गैर-सामान्य विधि के भीतर), मुझे डर है, संभव नहीं है। –

+0

बहुत बहुत धन्यवाद दान:) ​​ – SDReyes

0

ऐसा कुछ?

Func<Nullable<int>, string> myFunc = c => c.HasValue ? c.ToString() : "null";

सफलतापूर्वक संकलित यही कारण है, और आपको लगता है कि एक Nullable में ले जाता है और एक स्ट्रिंग रिटर्न कि के लिए किसी भी समारोह आवंटित कर सकते हैं।

+0

हाय क्यूबाक्स !, वास्तव में नहीं। आप एक लैम्ब्डा का संदर्भ दे रहे हैं जो एक निरर्थक वस्तु लेता है और एक स्ट्रिंग लौटाता है। मैं एक सामान्य विधि का संदर्भ देने की कोशिश कर रहा हूं (उदाहरण के लिए एक प्रकार टीएसओआर प्राप्त करता है) बहुत बहुत धन्यवाद! – SDReyes

0

हाँ यह संभव है, लेकिन आप जहां

class myClass 
{ 
    T returnsT<T>() 
    {...} 
} 

यह प्रकार तर्क बिना काम नहीं करेगा प्रकार तर्क (रों)

func<int> f = myClass.returnsT<int>; 

निर्दिष्ट करने के लिए

0

मैंने किया है की आवश्यकता होगी इस तरह कुछ:

public static class Helper{ 

public static IEnumerable<KeyValuePair<string, string>> ToPairs(this NameValueCollection Form) 
     { 
      return Form.AllKeys.Cast<string>() 
       .Select(key => new KeyValuePair<string, string>(key, Form[key])); 
     } 
} 

जहां यह विधि सी # वेब विकास में request.form के लिए एक विस्तार विधि बन गई है।

+0

हाय आर्ने, आपके उत्तर के लिए धन्यवाद। फिर भी यह एक सामान्य विधि नहीं है। धन्यवाद – SDReyes

4

हां, लेकिन यह संदर्भ पर निर्भर करता है - यदि आप पहले से ही जेनरिक के साथ काम कर रहे हैं, तो संदर्भ में टी का उपयोग करें/यदि नहीं, तो आप पहले से ही विशिष्ट प्रकार को जानते हैं। बाद में, यदि आपको किसी विधि पर थोड़ी-थोड़ी तर्क का पुन: उपयोग करने की आवश्यकता है, तो संभवतः आप इसे पहले से ही एक विधि में ले जाने का लाभ उठाएंगे, इसलिए बस नीचे अपना दूसरा उदाहरण पसंद करें।

2 नमूने:

public T Something<T>() { 
    Func<T> someFunc =() => { return default(T); }; 
    return someFunc(); 
} 

public Func<T> GetDefaultCreator<T>() { 
    return() => { return default(T); }; 
} 
+0

धन्यवाद फ्रेडी इतनी स्पष्ट +1 – SDReyes

0

मुझे लगता है कि मैं समझ गया: समारोह static TResult DoSomeStuff<T, TResult>(T obj) देखते हुए, आप बना सकते हैं एक Func<T, TResult> ऐसी है कि वह समारोह से ऊपर का संदर्भ लेंगे, संदर्भ के निर्माण में दिया कोई प्रकार मानकों के साथ इसके लिए
मुझे लगता है कि यह (आप यह परीक्षण करने के लिए आपका स्वागत है, मैं इस समय मेरे पास कोई सी # है) काम कर सकता था:

class UselessClass<T, TResult> 
{ 
    // If it's a static method, this is fine: 
    public Func<T, TResult> DaFunc = RelevantClass.DoSomeStuff<T, TResult>; 
    // If not, something like this is needed: 
    public UselessClass(SomeClassWhereTheFunctionIs from) 
    { 
     DaFunc = from.DoSomeStuff<T, TResult>; 
    } 
} 

इसके अलावा, OrderBy में, यह वास्तव में एक सामान्य प्रतिनिधि है। यह एक चर की घोषणा है। जब कार्य इसे दिया जाता है, तो इसका प्रकार अनुमानित होता है।

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