2016-06-17 3 views
5

पर विचार के बाद दो विस्तार तरीके:कंपाइलर IENumerable <T> पर IENumerable के साथ ओवरराइड क्यों चुनता है?

using System; 
using System.Collections.Generic; 
using System.Linq; 

public static class Extensions 
{ 
    public static bool Contains(this IEnumerable self, object obj) 
    { 
     foreach (object o in self) 
     { 
      if (Object.Equals(o, obj)) 
      { 
       return true; 
      } 
     } 
     return false; 
    } 

    public static bool ContainsEither<T>(this IEnumerable<T> self, T arg1, T arg2) 
    { 
     return self.Contains(arg1) || self.Contains(arg2); 
    } 
} 

मैं अपने दूसरी विधि लिखा है, मैं यह इरादा सामान्य LINQ Enumerable.Contains<T> विधि (प्रकार तर्क उपयोग से अनुमान लगाया) कॉल करने के लिए। हालांकि, मुझे पता चला कि यह वास्तव में पहली विधि बुला रहा है कि (अपने कस्टम Contains() विस्तार विधि। जब मैं बाहर टिप्पणी मेरी Contains() विधि, दूसरी विधि ठीक संकलित, Enumerable.Contains<T>() पद्धति का उपयोग करके।

मेरा प्रश्न है, क्यों करता है संकलक IEnumerable<T> तर्क के साथ Enumerable.Contains<T>() से अधिक गैर सामान्य IEnumerable तर्क के साथ अपने Contains() विधि का चयन मैं इसे Enumerable.Contains<T>() क्योंकि IEnumerable<T> अधिक IEnumerable से ली गई है चुनने के लिए उम्मीद करेंगे

अद्यतन:?।। महान उत्तर के लिए जॉन स्कीट के लिए धन्यवाद यह होगा यह जानकर दिलचस्प है कि डिजाइनरों ने इस तरह क्यों चुना। मैंने कुछ समय तलाशने में बिताया यहीं से इस बात हैं, मैं एक के बारे में सोचा (दी यह एक पहुंच का एक सा)

public static double Average(this IEnumerable self) 
{ 
    double sum = 0; 
    long count = 0; 
    foreach (object obj in self) 
    { 
     sum += Convert.ToDouble(obj); 
     nItems++; 
    } 
    return sum/count; 
} 

object[] junk = new object[] { "9000", (byte)99, -8.555, 3154254325345UL }; 
double[] clean = new double[] { 9000, 99, -8.555, 3154254325345 }; 
double junkAvg = junk.Average(); 
double cleanAvg = clean.Average(); // compiler is choosing your Average() method where you'd prefer it to choose Enumerable.Average(IEnumerable<double>) 
+0

जेनरिक अधिक विशिष्ट हैं। –

+0

सामान्य रूप से, इस तरह की स्थितियों में, सवाल "क्यों" आम तौर पर दिलचस्प होता है, लेकिन शायद यह अधिक महत्वपूर्ण सवाल है कि "मैं इसे कैसे नहीं बना सकता ....."। –

+0

@ LasseV.Karlsen वास्तव में क्यों बस के बारे में। मैं संख्यात्मक लिखा होगा। (...) या (...) शामिल है –

उत्तर

20

मेरा प्रश्न है, क्यों संकलक गैर सामान्य IEnumerableEnumerable.Contains<T>() से अधिक तर्क के साथ चयन करता है मेरी शामिल() विधि IEnumerable<T> तर्क के साथ?

क्योंकि यह उसी नामस्थान में पाया गया है जिसमें इसे कॉल करने की विधि शामिल है। उस नेमस्पेस के भीतर घोषित प्रकार प्रभावी रूप से आयातित नामस्थानों में घोषित प्रकारों पर प्राथमिकता रखते हैं।

सी # 5 विनिर्देश से, खंड 7.6.5.2:

सी आय के लिए खोज इस प्रकार है:

  • , निकटतम संलग्नित नाम स्थान घोषणा के साथ शुरू प्रत्येक enclosing नाम स्थान घोषणा के साथ जारी और युक्त संकलन इकाई के साथ समाप्त होने के बाद, प्रयास विधियों के उम्मीदवार सेट को खोजने के लिए लगातार प्रयास किए जाते हैं:
    • यदि दिया गया नामस्थान या संकलन एन यूनिट में सीधे गैर-सामान्य प्रकार की घोषणाएं सीआई योग्य विस्तार विधियों एमजी के साथ होती हैं, फिर उन एक्सटेंशन विधियों का सेट उम्मीदवार सेट होता है।
    • यदि दिए गए नेमस्पेस या संकलन इकाई में नेमस्पेस निर्देशों का उपयोग करके आयात किए गए नामस्थान सीधे योग्य विस्तार विधियों एमजे के साथ गैर-सामान्य प्रकार की घोषणा सीआई होते हैं, तो उन एक्सटेंशन विधियों का सेट उम्मीदवार सेट होता है।
  • यदि किसी भी नामांकन सेट किसी भी संलग्न नामस्थान घोषणा या संकलन इकाई में कोई उम्मीदवार सेट नहीं मिलता है, तो संकलन-समय त्रुटि होती है।
संबंधित मुद्दे