2008-10-02 2 views
250

में टाइपपीफ के समतुल्य क्या सी # में एक टाइपिफ़ समतुल्य है, या किसी तरह का व्यवहार करने के लिए किसी तरह का तरीका है? मैंने कुछ googling किया है, लेकिन हर जगह मैं नकारात्मक लगता है। वर्तमान में मैं एक स्थिति निम्न के समान है:सी #

class GenericClass<T> 
{ 
    public event EventHandler<EventData> MyEvent; 
    public class EventData : EventArgs { /* snip */ } 
    // ... snip 
} 

अब, यह एक रॉकेट वैज्ञानिक जब कोशिश कर नहीं ले करता है यह पता लगाने की (भयानक यमक के लिए क्षमा याचना) है कि इस बहुत जल्दी लिखने का बहुत बढ़ सकता है उस घटना के लिए एक हैंडलर लागू करने के लिए। , मैं पहले से ही जटिल प्रकार, न सिर्फ एक पूर्णांक उपयोग कर रहा था

GenericClass<int> gcInt = new GenericClass<int>; 
gcInt.MyEvent += new EventHandler<GenericClass<int>.EventData>(gcInt_MyEvent); 
// ... 

private void gcInt_MyEvent(object sender, GenericClass<int>.EventData e) 
{ 
    throw new NotImplementedException(); 
} 

छोड़कर, मेरे मामले में: यह कुछ इस तरह किया जा रहा है पहुंचते हैं। यह अच्छा होगा अगर इसे थोड़ा सा सरल बनाना संभव हो ...

संपादित करें: यानी। संभवतः इवेंट हैंडलर को टाइप करने के बजाय इसे समान व्यवहार प्राप्त करने के लिए इसे फिर से परिभाषित करने की आवश्यकता है।

उत्तर

273

नहीं, टाइपपीफ के कोई वास्तविक समकक्ष नहीं है। आप एक फ़ाइल के भीतर 'उपयोग' निर्देशों का उपयोग कर सकते हैं, उदा।

using CustomerList = System.Collections.Generic.List<Customer>; 

लेकिन इससे केवल उस स्रोत फ़ाइल को प्रभावित किया जाएगा। सी और सी ++ में, मेरा अनुभव यह है कि typedef आमतौर पर .h फ़ाइलों के भीतर उपयोग किया जाता है जो व्यापक रूप से शामिल होते हैं - इसलिए एक पूरे प्रोजेक्ट पर एक typedef का उपयोग किया जा सकता है। यह क्षमता सी # में मौजूद नहीं है, क्योंकि सी # में कोई #include कार्यक्षमता नहीं है जो आपको using निर्देशों को एक फ़ाइल से दूसरे में शामिल करने की अनुमति देगी।

सौभाग्य से, उदाहरण में एक फिक्स - अंतर्निहित विधि समूह रूपांतरण है। तुम बस करने के लिए अपने घटना सदस्यता लाइन बदल सकते हैं:

gcInt.MyEvent += gcInt_MyEvent; 

:)

+11

मैं हमेशा भूल जाता हूं कि आप यह कर सकते हैं। शायद क्योंकि विजुअल स्टूडियो अधिक वर्बोज संस्करण का सुझाव देता है। लेकिन मैं टैब दबाने दो बार के बजाय हैंडलर नाम टाइप के साथ ठीक हूँ, मेरे अनुभव में) – OregonGhost

+11

(जो दुर्लभ है), तो आप उदाहरण के लिए, पूरी तरह से योग्य प्रकार नाम निर्दिष्ट करने के लिए है: 'का उपयोग कर MyClassDictionary = System.Collections। Generic.Dictionary ; ' क्या यह सही है? अन्यथा यह उपरोक्त 'उपयोग' परिभाषाओं पर विचार नहीं करता है। – tunnuz

+2

@tunnuz: हाँ, आप सही हैं - मैं जवाब अपडेट कर दूंगा। –

5

मुझे लगता है कि कोई typedef है। आप केवल एक विशिष्ट प्रतिनिधि प्रकार के बजाय GenericClass में सामान्य से एक है, यानी

public delegate GenericHandler EventHandler<EventData> 

यह छोटा बना देने वाले को परिभाषित कर सकते हैं। लेकिन निम्नलिखित सुझावों के बारे में क्या:

विजुअल स्टूडियो का उपयोग करें। इस तरह, जब आपने टाइप किया

gcInt.MyEvent += 

यह पहले से ही इंटेलिसेंस से पूर्ण ईवेंट हैंडलर हस्ताक्षर प्रदान करता है। टैब दबाएं और यह वहां है। जेनरेट किए गए हैंडलर नाम को स्वीकार करें या इसे बदलें, और फिर हैंडलर स्टब को स्वतः उत्पन्न करने के लिए फिर से टैब दबाएं।

+2

हाँ, उदाहरण के लिए मैंने यही किया। लेकिन फिर से देखने के लिए वापस आना तथ्य के बाद भी भ्रमित हो सकता है। –

+0

मुझे पता है तुम्हारा क्या मतलब है। यही कारण है कि मैं अपने घटना हस्ताक्षर कम रखने के लिए, या अपने खुद के प्रतिनिधि प्रकार के बजाय सामान्य eventhandler उपयोग करने के लिए FxCop सिफारिश से दूर होने के लिए करना चाहते हैं। लेकिन फिर, लघु हाथ जॉन स्कीट :) – OregonGhost

+2

आप ReSharper मिल गया है, तो यह आपको बता दूँगा लंबे संस्करण overkill है कि (ग्रे में यह रंग से) द्वारा प्रदान की संस्करण के साथ चिपके रहते हैं, और आप एक "जल्दी उपयोग कर सकते हैं इसे फिर से छुटकारा पाने के लिए "ठीक करें। –

33

जॉन ने वास्तव में एक अच्छा समाधान दिया, मुझे नहीं पता था कि आप ऐसा कर सकते हैं!

कभी-कभी मैंने जो कक्षा का सहारा लिया वह कक्षा से विरासत में था और इसके रचनाकारों को बना रहा था। जैसे

public class FooList : List<Foo> { ... } 

सबसे अच्छा समाधान नहीं है (जब तक आपकी असेंबली अन्य लोगों द्वारा उपयोग नहीं की जाती), लेकिन यह काम करता है।

+34

निश्चित रूप से एक अच्छी विधि है, लेकिन ध्यान रखें कि उन (कष्टप्रद) मुहरबंद प्रकार मौजूद हैं, और यह वहां काम नहीं करेगा। मैं वास्तव में चाहता हूं कि सी # पहले से ही टाइपपीफ पेश करेगी। यह एक बेताब आवश्यकता है (विशेष रूप से सी ++ प्रोग्रामर के लिए)। – MasterMastic

+0

मैंने इस स्थिति के लिए एक परियोजना बनाई है जिसे लाइकटाइप कहा जाता है जो इसे प्राप्त करने के बजाय अंतर्निहित प्रकार को लपेटता है। यह भी परोक्ष, अंतर्निहित प्रकार _TO_ में परिवर्तित कर देंगे ताकि आप 'सार्वजनिक वर्ग FooList की तरह कुछ इस्तेमाल कर सकते हैं: LikeType > {...}' और फिर कहीं भी आप उम्मीद करेंगे एक 'IReadOnlyList ' में उपयोग करें। [मेरा जवाब] (http://stackoverflow.com/a/35973121/1672027) नीचे अधिक जानकारी दिखाता है। –

+2

यह उत्तीर्ण होने पर 'Foo' प्रकार का अनुमान नहीं लगाएगा। टेम्पलेट विधि जो 'सूची 'स्वीकार करती है। उचित टाइपिफ़ के साथ यह संभव होगा। –

6

सी # किसी घटना प्रतिनिधियों के लिए सहप्रसरण विरासत में मिला समर्थन करता है, तो इस तरह की एक विधि:

void LowestCommonHander(object sender, EventArgs e) { ... } 

आपके घटना की सदस्यता के लिए इस्तेमाल किया जा सकता है, कोई स्पष्ट डाली आवश्यक

gcInt.MyEvent += LowestCommonHander; 

तुम भी उपयोग कर सकते हैं लैम्ब्डा सिंटैक्स और इंटेलिजेंस आपके लिए किया जाएगा:

gcInt.MyEvent += (sender, e) => 
{ 
    e. //you'll get correct intellisense here 
}; 
+0

मैं गंभीरता से (2008 वी.एस. हालांकि में) –

+0

ओह, भी, मैं ठीक, सदस्यता ले सकते हैं रिकॉर्ड के लिए Linq अच्छी तरह से देखने ... होने हालांकि, मैं समय पर 2.0 के लिए निर्माण कर रहा था करने के लिए चारों ओर हो रही करने की जरूरत है, लेकिन फिर पाने के लिए घटना तर्कों पर मुझे एक स्पष्ट कलाकार की आवश्यकता होती है, और अधिमानतः सुरक्षित कोड पर रहने के लिए चेकिंग कोड टाइप करें। –

+7

वाक्य रचना सही है, लेकिन मैं इसे "Linq वाक्य रचना" नहीं कहेंगे; बल्कि यह एक लैम्ब्डा अभिव्यक्ति है। लैम्ब्डास एक सहायक विशेषता है जो लिंक काम करता है, लेकिन पूरी तरह से स्वतंत्र है। अनिवार्य रूप से, कहीं भी आप एक प्रतिनिधि का उपयोग कर सकते हैं, आप एक लैम्ब्डा अभिव्यक्ति का उपयोग कर सकते हैं। –

16

यदि आप जानते हैं कि आप क्या कर रहे हैं, आप उपनाम वर्ग और वास्तविक वर्ग के बीच परिवर्तित करने के लिए निहित ऑपरेटरों के साथ एक कक्षा को परिभाषित कर सकते हैं।

class TypedefString // Example with a string "typedef" 
{ 
    private string Value = ""; 
    public static implicit operator string(TypedefString ts) 
    { 
     return ((ts == null) ? null : ts.Value); 
    } 
    public static implicit operator TypedefString(string val) 
    { 
     return new TypedefString { Value = val }; 
    } 
} 

मैं वास्तव में इसका समर्थन नहीं करता हूं और कभी ऐसा कुछ नहीं किया है, लेकिन यह शायद कुछ विशिष्ट परिस्थितियों के लिए काम कर सकता है।

+0

धन्यवाद @ पल्सविम, मुझे यहां कुछ टाइप किया गया है जैसे "typedef string Identifier;" तो आपका सुझाव सिर्फ वही हो सकता है जो मुझे चाहिए। – yoyo

2

आप एक ओपन सोर्स लाइब्रेरी और NuGet पैकेज का उपयोग कर सकते हैं जिसे LikeType कहा जाता है जिसे मैंने बनाया है जो आपको GenericClass<int> व्यवहार देगा जो आप खोज रहे हैं।

कोड लगेगा जैसे:

public class SomeInt : LikeType<int> 
{ 
    public SomeInt(int value) : base(value) { } 
} 

[TestClass] 
public class HashSetExample 
{ 
    [TestMethod] 
    public void Contains_WhenInstanceAdded_ReturnsTrueWhenTestedWithDifferentInstanceHavingSameValue() 
    { 
     var myInt = new SomeInt(42); 
     var myIntCopy = new SomeInt(42); 
     var otherInt = new SomeInt(4111); 

     Assert.IsTrue(myInt == myIntCopy); 
     Assert.IsFalse(myInt.Equals(otherInt)); 

     var mySet = new HashSet<SomeInt>(); 
     mySet.Add(myInt); 

     Assert.IsTrue(mySet.Contains(myIntCopy)); 
    } 
} 
+0

क्या डाउनवोट टिप्पणी करने की देखभाल करेगा? –

4

यहाँ इसके लिए कोड है, का आनंद !, मुझे लगता है कि नाम स्थान की रेखा के भीतर बयान "का उपयोग कर" उठाया dotNetReference प्रकार से 106 http://referencesource.microsoft.com/#mscorlib/microsoft/win32/win32native.cs

using System; 
using System.Collections.Generic; 
namespace UsingStatement 
{ 
    using Typedeffed = System.Int32; 
    using TypeDeffed2 = List<string>; 
    class Program 
    { 
     static void Main(string[] args) 
     { 
     Typedeffed numericVal = 5; 
     Console.WriteLine(numericVal++); 

     TypeDeffed2 things = new TypeDeffed2 { "whatever"}; 
     } 
    } 
}