2009-10-22 16 views
10

के साथ विधि ओवरलोडिंग मैं सोच रहा था कि निम्नलिखित संभव है या नहीं। एक वर्ग बनाएं जो अनाम प्रकार (स्ट्रिंग, int, दशमलव, customObject, आदि) स्वीकार करता है, उसके बाद ओवरलोडेड विधियां हैं जो प्रकार के आधार पर अलग-अलग संचालन करती हैं। उदाहरणप्रकार सी #

class TestClass<T> 
{ 
    public void GetName<string>() 
    { 
     //do work knowing that the type is a string  
    } 

    public string GetName<int>() 
    { 
     //do work knowing that the type is an int 

    } 

    public string GetName<int>(int addNumber) 
    { 
     //do work knowing that the type is an int (overloaded)  
    } 

    public string GetName<DateTime>() 
    { 
     //do work knowing that the type is a DateTime 

    } 

    public string GetName<customObject>() 
    { 
     //do work knowing that the type is a customObject type  
    } 

} 

तो अब मैं getName विधि कह सकते हैं, और क्योंकि मैं पहले से ही प्रकार में पारित कर दिया जब मैं वस्तु प्रारंभ, सही विधि पाया जाता है और मार डाला जाता है।

TestClass foo = new TestClass<int>(); 

//executes the second method because that's the only one with a "int" type 
foo.GetName(); 

क्या यह संभव है या मैं बस सपना देख रहा हूं?

उत्तर

12

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

class TestClass<T> 
{ 
    public string GetName<T>() 
    { 
     Type typeOfT = typeof(T); 
     if(typeOfT == typeof(string)) 
     { 
      //do string stuff 
     } 
    } 
} 

हालांकि यह संभव है, आप एक तरह से जेनरिक के प्रयोजन को हराने कर रहे हैं। जेनेरिक का बिंदु तब होता है जब मामला नहीं है, इसलिए मुझे नहीं लगता कि इस मामले में जेनेरिक उचित है।

0

कक्षा विस्तार विधियों का उपयोग करना आपके लिए काम करेगा?

आप अनिवार्य रूप से अपनी इच्छित कक्षाओं में विधियां जोड़ सकते हैं, और फिर आप इसे उसी तरह से कॉल कर सकते हैं।

namespace ExtensionMethods 
{ 
    public static class MyExtensions 
    { 
     public static int GetName(this String str) 
     { 
      ... 
     } 
    } 
} 

का उपयोग कर कहा जाता है:

myString.GetName(); 
4

"विशेषज्ञता" संभव नहीं सी # में जिस तरह से यह सी में है ++। .NET जेनेरिक में, < टी > का एक सामान्य वर्ग या विधि टी के सभी संभावित मानों के लिए समान होना चाहिए। यह रनटाइम को दो अलग-अलग संदर्भ प्रकारों को ऑप्टिमाइज़ेशन करने की अनुमति देता है, टेस्टक्लास < स्ट्रिंग > और टेस्टक्लास < सूची <int> >, उसी मशीन भाषा कोड को साझा करें। (अलग मूल्य प्रकार अलग मशीन कोड मिलता है, लेकिन आप अभी भी विशेषज्ञ नहीं कर सकते।)

मुझे लगता है यह कभी कभी एक सामान्य इंटरफ़ेस या इस तरह आधार वर्ग बनाने के लिए मदद करता है:

abstract class Base<T> { 
    public abstract T GetName(); 
    // any common code goes here that does not require specialization 
} 

और व्युत्पन्न में विशेषज्ञता करना कक्षाएं:

class IntVersion : Base<int> { 
    public override int GetName() { return 1; } 
    public int GetName(int addNumber) { ... } 
} 
class StringVersion : Base<string> { 
    public override string GetName() { return "foo"; } 
} 
class DateTimeVersion : Base<DateTime> { 
    public override DateTime GetName() { return DateTime.Now; } 
} 
+0

+1 जेनरिक! = टेम्पलेट्स – user7116

1

नहीं, यह संभव नहीं है। आप जो करने की कोशिश कर रहे हैं वह सी ++ में टेम्पलेट विशेषज्ञता के समान है, जो सी # में (दुख की बात है) संभव नहीं है।

आप विशेष कार्यान्वयन आह्वान करने के लिए

typeof(T) 

पर करने के लिए करता है, तो/बाकी या स्विच की जरूरत है।

हालांकि, अगर आप टी के प्रकार में रोके कर सकते हैं या तो एक वर्ग (संदर्भ मूल्य) या struct (मान) या एक निश्चित baseclass के उपवर्ग इसलिए की तरह बनना:

public Foo<T> DoBar<T>() where T : FooBase; 
0

सी # के लिए समर्थन नहीं है इस तरह के प्रेषण।

और विधि ओवरलोडिंग करने के लिए यह सही तरीका नहीं है (त्रुटि 'टेस्ट क्लास' पहले से ही < के अंदर 'गेटनाम' नामक एक सदस्य को परिभाषित करता है, जब तक कि सभी विधि हस्ताक्षर का हिस्सा नहीं है।

3

सी # में विशेषज्ञता संभव नहीं है। सी # में निकटतम बात निम्नलिखित

public void Example() { 
    public static void Method<T>(T value) { ... } 
    public static void Method(int value){ ... } 
    public static void Method(string) { ... } 
} 

सी # संकलक एक सामान्य पद्धति पर एक गैर सामान्य विधि पसंद करते हैं जाएगा। इसका मतलब यह है कि एक इंट पैरामीटर के साथ कॉल करना सामान्य रूप से int अधिभार बनाम होगा।

Example.Method(42); // Method(int) 
Example.Method(new Class1()) // Method<T>(T) 

यह आपको हालांकि काटने क्योंकि यह जब विधि सामान्य रूप से कहा जाता है लागू नहीं होता होगा। उस स्थिति में यह सामान्य मामला से बंधेगा चाहे कोई भी प्रकार न हो।

public void Gotcha<T>(T value) { 
    Example.Method(value); 
} 

Gotcha(42); // Still calls Example.Method<T>() 
0

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

एक उदाहरण:

abstract class TestClass<T> 
{ 
    public List<T> Items { get; set; } 

    // other generic (i.e. non type-specific) code 
} 

class IntTestClass : TestClass<int> 
{ 
    public string GetName() 
    { 
     // do work knowing that the type is an int 
    } 

    // other code specific to the int case 
} 

class StringTestClass : TestClass<string> 
{ 
    public string GetName() 
    { 
     // do work knowing that the type is a string 
    } 

    // other code specific to the string case 
} 
0

BFree के रूप में अगर पेड़, या अधिक होने की संभावना एक स्विच बयान आप एक साथ कर सकते हैं उल्लेख किया है, लेकिन कुछ बिंदु पर आप चाहते हैं जाएगा तुम सिर्फ तरीकों लिख सकता है और जाने नेट इसे समझें, खासकर यदि आप समय के साथ अधिभार की लाइब्रेरी विकसित करते हैं।

समाधान प्रतिबिंब है, हालांकि यह नेट में बहुत सस्ता प्रदर्शन के लिहाज से है:

using System.Reflection; 
... 

public string DoSomething(object val) 
{ 
    // Force the concrete type 
    var typeArgs = new Type[] { val.GetType() }; 

    // Avoid hard-coding the overloaded method name 
    string methodName = new Func<string, string>(GetName).Method.Name; 

    // Use BindingFlags.NonPublic instead of Public, if protected or private 
    var bindingFlags = BindingFlags.Public | BindingFlags.Instance; 

    var method = this.GetType().GetMethod(
     methodName, bindingFlags, null, typeArgs, null); 

    string s = (string)method.Invoke(this, new object[] { val }); 

    return s; 
} 

आप मूल रूप से सिर्फ प्रतिबिंब ढांचे कह रहे हैं आप के लिए है कि स्विच बयान कर जाने के लिए।