2013-05-06 4 views
19

मान लीजिए मैं एक स्वेच्छापूर्ण सामान्य विधि है कि सभी प्रकार के समानता के समर्थन पर काम करता है। यह जोड़ो में समानता जाँचों का निष्पादन और इसलिए में काम करता है O (n):सशर्त रूप से बाधाओं के साथ एक सामान्य विधि का आह्वान कैसे करें?

public static int CountDuplicates<T>(IList<T> list) 
{ 
    /* ... */ 
} 

मैं भी एक विवश सामान्य विधि है कि केवल प्रकार छँटाई समर्थन के साथ काम करता है। यह हे में सूची को क्रमबद्ध (एन लॉग इन करें n) से शुरू होता है, और फिर एक पास में सभी डुप्लिकेट मायने रखता है:

public static int CountDuplicatesFast<T>(IList<T> list) 
    where T : IComparable<T> 
{ 
    /* ... */ 
} 

तो, एक फोन करने वाले तेज विधि आह्वान करने के लिए चुन सकते हैं अगर यह स्थिर है कि जाना जाता है सूची के तत्वों का प्रकार ऑर्डर करने का समर्थन करता है। यह हो सकता है कि फोन करने वाले ही सामान्य IList<T> साथ काम करता है जहां टी स्वेच्छापूर्ण है, इसलिए पहले (धीमा) विधि आह्वान करने के लिए अपने ही एकमात्र विकल्प।

public static int CountDuplicates<T>(IList<T> list) 
{ 
    if (typeof(IComparable<T>).IsAssignableFrom(typeof(T))) 
    { 
     return CountDuplicatesFast(list); 
    } 
    else 
    { 
     /* use the slow algorithm */ 
    } 
} 

समस्या संकलक मंगलाचरण CountDuplicatesFast(list) को खारिज कर दिया है:

अब, मैं पहली विधि, कार्यावधि में जांच करने के लिए करता है, तो प्रकार T वास्तव में इंटरफ़ेस IComparable<T> लागू करता है और यदि ऐसा है तो तेजी से विधि आह्वान हैं:

त्रुटि CS0314: प्रकार 'टी' सामान्य प्रकार या विधि के रूप में प्रकार पैरामीटर 'टी' नहीं किया जा सकता 'Program.CountDuplicatesFast < टी > (System.Collections.Generic.IList < टी >) '। 'टी' से 'System.IComparable < टी >' से कोई मुक्केबाजी रूपांतरण या प्रकार पैरामीटर रूपांतरण नहीं है।

क्या मुझे विश्वास करने के लिए संकलक को राजी करना संभव है कि मुझे पता है कि मैं क्या कर रहा हूं, और बाधा जांच को छोड़ने के लिए?

+1

आप कास्ट उपयोग करने की कोशिश की है? 'लौट CountDuplicatesFast (list.Cast >() ToList()।);' – Nevyn

+0

@Nevyn कि "प्रकार 'System.IComparable ' का उत्पादन सामान्य प्रकार के रूप में प्रकार पैरामीटर 'टी' नहीं किया जा सकता या विधि 'UserQuery.MyType.CountDuplicatesFast (System.Collections.Generic.IList )' 'सिस्टम.कॉमपरेबल ' से सिस्टम सिस्टम में कोई अंतर्निहित संदर्भ रूपांतरण नहीं है। सिस्टम। अतुलनीय > '। –

+0

दिलचस्प। लगभग सही ट्रैक, लेकिन पूरी तरह से गलत निष्पादन।मुझे लगता है कि मुझे वास्तव में एक परीक्षा कार्यक्रम लिखना होगा और कुछ अलग-अलग चीजों को आजमाएं। मुझे लगता है कि कास्ट इसे करने में सक्षम हो सकता है ... लेकिन मुझे नहीं पता कि वास्तव में ... ओह ठीक है, पहले अनुमान के लिए यह बहुत दूर नहीं था :-) – Nevyn

उत्तर

7

यहाँ यह करने के लिए एक तरह से dynamic का उपयोग कर रहा है:

if (typeof(IComparable<T>).IsAssignableFrom(typeof(T))) 
{ 
    return CountDuplicatesFast((dynamic)list); 
} 

या प्रतिबिंब के साथ:

if (typeof(IComparable<T>).IsAssignableFrom(typeof(T))) 
{ 
    var method = typeof(MyType).GetMethod("CountDuplicatesFast"); 
    var generic = method.MakeGenericMethod(typeof(T)); 
    return (int)generic.Invoke(null, new object[] { list }); 
} 

मुझे नहीं लगता कि यह स्थिर करने के लिए एक तरीका है कि वहाँ है (यानी प्रतिबिंब या dynamic बिना)।

+3

अच्छा! मैंने तर्क कास्टिंग करने के बारे में नहीं सोचा था। मुझे लगता है कि मेरे दृष्टिकोण की आवश्यकता केवल दुर्लभ मामलों में होती है जब एक प्रकार पैरामीटर होता है लेकिन कोई मान पैरामीटर नहीं होता है। –

+0

@VladimirReshetnikov hm..how तब भी मदद मिलेगी? जब तक सहायक वर्ग ने प्रकार को अनुमानित करने के लिए डमी पैरामीटर जोड़ा, तब तक मुझे यह नहीं दिखाई देता। –

8

आप संकलन-समय जांचें करता छोड़ एक सहायक वर्ग और dynamic प्रकार का उपयोग कर सकते हैं:

sealed class CountDuplicatesFastCaller 
{ 
    public int Call<T>(IList<T> list) where T : IComparable<T> 
    { 
     return CountDuplicatesFast(list); 
    } 
} 

public static int CountDuplicates<T>(IList<T> list) 
{ 
    if (typeof (IComparable<T>).IsAssignableFrom(typeof (T))) 
    { 
     return ((dynamic) new CountDuplicatesFastCaller()).Call(list); 
    } 
    else 
    { 
     /* use the slow algorithm */ 
    } 
} 

इसका कारण यह है डीएलआर कैशिंग प्रणाली का शुद्ध प्रतिबिंब की तुलना में तेजी से किया जाना चाहिए।

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