2009-12-17 8 views
17

शायद मैं सी # या .NET ढांचे के कुछ उपयोग किए गए feautre की अपनी अज्ञानता का प्रदर्शन कर रहा हूं, लेकिन मैं जानना चाहता हूं कि EmailAddress जैसे प्रकार के उपनाम बनाने के लिए एक मूल रूप से समर्थित तरीका है जो string उपनाम करता है लेकिन ऐसा है कि मैं इसे bool Validate() जैसे अपने तरीकों से बढ़ा सकते हैं?क्या मौजूदा स्ट्रिंग-टाइप किए गए उपनामों को 'स्ट्रिंग` या' int` जैसे सी # दृढ़ता से टाइप किए गए उपनाम परिभाषित करने का कोई तरीका है?

मुझे using x = Some.Type; उपनामों के बारे में पता है, लेकिन ये वैश्विक नहीं हैं और न ही वे प्रकार की सुरक्षा प्रदान करते हैं, यानी कोई मौजूदा फ़ाइल में उपयोग उपनाम के लिए सामान्य string को स्वैप कर सकता है। मैं अपने EmailAddress को अपने स्वयं के प्रकार, स्वतंत्र और string के साथ विनिमेय नहीं होना चाहता हूं, जो कि यह छाया करता है।

मेरा वर्तमान समाधान बॉयलरप्लेट निहित स्ट्रिंग रूपांतरण ऑपरेटरों और अन्य ऐसी चीजों को उत्पन्न करने वाले टी 4 टेम्पलेट के साथ public sealed partial EmailAddress : IEquatable<EmailAddress>, IXmlSerializable कक्षाएं उत्पन्न करना है। यह मेरे लिए अभी ठीक है और मुझे बहुत लचीलापन देता है लेकिन मेरे दिमाग के पीछे यह मूर्खतापूर्ण लगता है कि मुझे बॉयलरप्लेट कोड की इतनी भारी मात्रा उत्पन्न करने के लिए एक मजबूत प्रकार उपनाम बनाने के रूप में सरल कुछ करना है।

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

संपादित करें: वास्तविक मूल्य जो मैं चाहता हूं वह प्राचीन प्रकार के साथ प्रकार की सुरक्षा प्राप्त करने में सक्षम होना है जो डेटा के लिए विभिन्न प्रकार/प्रारूपों का प्रतिनिधित्व करता है। उदाहरण के लिए, EmailAddress और SocialSecurityNumber और PhoneNumber, जिनमें से सभी string का उपयोग उनके अंतर्निहित प्रकार के रूप में करते हैं, लेकिन जो स्वयं और उनके बीच विचलित प्रकार नहीं हैं। मुझे लगता है कि यह आपको अधिक पढ़ने योग्य और स्वयं-दस्तावेज कोड प्राप्त करता है, अधिक अस्पष्ट अधिभार संभावनाओं के अतिरिक्त लाभों का उल्लेख नहीं करना जो कम अस्पष्ट हैं।

+0

इसे क्यों वोट दें और कोई टिप्पणी न छोड़ें? चलो करते हैं। – JMD

+1

ऐसा लगता है कि आपके पास कम से कम एक उचित सी # knoledgde है इसलिए मेरी टिप्पणी बेवकूफ लग सकती है, लेकिन आप जो चाहते हैं उसे "टाइप पदानुक्रम" कहा जाता है और स्ट्रिंग क्लास को कोड करने वाले लोग आपको "ओओ फीचर" का उपयोग करने से रोकना चाहते थे ताकि वे बने स्ट्रिंग क्लास सील कर दिया गया है, यही कारण है कि आप जो भी चाहते हैं वह करने में सक्षम नहीं होंगे। सबसे अच्छा तरीका यह है कि आप अभी इस पर हैं: अपना स्वयं का प्रकार बनाएं और स्ट्रिंग में एक अंतर्निहित रूपांतरण करें। –

+0

@Andre: क्यों नहीं टिप्पणी के रूप में अपनी टिप्पणी पोस्ट करने पर विचार करें? –

उत्तर

4

यदि आप .NET Framework System को देखते हैं। यूरी निकटतम उदाहरण है जो ईमेल पते के समान है। .NET में पैटर्न किसी वर्ग में कुछ लपेटना और उस तरह की बाधाओं को जोड़ना है।

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

+0

यह जाने का सबसे अच्छा तरीका लगता है। मैं कार्यात्मक भाषाओं में अच्छी तरह से नहीं जानता हूं लेकिन मुझे पता है कि उनके पास कुछ निफ्टी प्रकार की प्रणालियों हैं जो आपको ऑब्जेक्ट उन्मुख की तुलना में बहुत अच्छी तरह लिखने देती हैं। –

+1

मेरा मानना ​​है कि एडा भाषा में आपके द्वारा वर्णित सुविधा है, या एक समान है। – AakashM

+0

गो और हास्केल में भी ऐसी बाधाएं हैं (मुझे यकीन है कि गो, हास्केल मुझे अच्छी तरह से पता नहीं है)। – Crisfole

2

क्या System.Net.Mail.MailAddress कक्षा आपकी आवश्यकताओं के अनुरूप है, या कम से कम "सहायता"?

संपादित करें: यह स्पष्ट रूप से IEquatable या ISerializable नहीं है, लेकिन आप आसानी से अपने स्वयं के रैपर में पर्याप्त जोड़ सकते हैं।

+1

नहीं, मैं सामान्य समाधान मांगना चाहता था, ईमेल पते का विशिष्ट मामला नहीं। मैं स्वयं को दस्तावेज उद्देश्यों और विधि अधिभार परिभाषाओं में flexibilty के लिए दृढ़ता से टाइप पहचानकर्ता बनाने के लिए 'int' wrappers उत्पन्न करने जैसी चीजें भी कर रहा हूं। उदाहरण के लिए मेरे पास एक ही इंटरफ़ेस पर परिभाषित दोनों 'कर्मचारी GetStaff (StaffID आईडी)' और 'कर्मचारी GetStaff (TeacherID आईडी) 'दोनों हैं। दोनों विधियों अंतर्निहित डेटा स्रोत के खिलाफ अलग-अलग प्रश्न पूछते हैं जो कि पहचानकर्ता प्रकार प्रदान किए जाते हैं। शिक्षक है- एक कर्मचारी और मूल्य 1 का शिक्षक एक समान इकाई का प्रतिनिधित्व नहीं करता है क्योंकि स्टाफ आईडी मूल्य 1 के साथ है। –

+0

समझा, मैंने इस प्रश्न के बारे में पूछे जाने पर आपके प्रश्न का गलत व्याख्या किया। – JMD

4

क्यों string बंद है पर कुछ पृष्ठभूमि:

http://www.code-magazine.com/Article.aspx?quickid=0501091 से:

रोरी: अरे जे, आप बुरा करता है, तो मैं तुम्हें एक कुछ सवाल पूछना? मैं कुछ चीजों के बारे में पहले से उत्सुक हूं। सबसे पहले, और यह इस सप्ताह किए गए एमएसडीएन घटनाओं में से एक में लाया गया था, स्ट्रिंग क्यों सील कर दिया गया है? नोट: वीबी.नेट प्रोग्रामर के लिए, मुहरबंद = NotInheritable।

जे: हम स्ट्रिंग में जादू चाल का एक बहुत कोशिश करते हैं और यह सुनिश्चित करें हम तुलना जैसी चीजों के लिए अनुकूलन कर सकते हैं, उन्हें जितनी जल्दी हम कर सकते हैं के रूप में बनाने के लिए बनाने के लिए क्या वजह। इसलिए, हम चीजों को चिह्नित करने के लिए पॉइंटर्स और अन्य चीजों से बिट्स चोरी कर रहे हैं।बस आपको एक उदाहरण देते हैं, और जब मैंने शुरू किया, तो मुझे पता नहीं था, लेकिन यदि स्ट्रिंग में में एक हाइफ़न या एस्ट्रोफ़े है तो [0] यह से अलग है, इसमें बस टेक्स्ट है, और यह छँटाई यदि आप एक हाइफ़न या एपोस्ट्रोफ़ी अगर आप विश्व स्तर पर अवगत छंटाई कर रहे हैं के लिए एल्गोरिथ्म सुंदर जटिल है, इसलिए हम वास्तव में चिह्नित किया जाए या नहीं स्ट्रिंग है कि यह में व्यवहार के प्रकार।

रोरी: तो, क्या तुम कह रहे हो कि स्ट्रिंग दुनिया में , यदि आप नहीं सील स्ट्रिंग किया वहाँ कमरे की एक पूरी बहुत कुछ कहर का एक बहुत तेज थी के लिए हो सकता है अगर लोगों के लिए कोशिश कर रहे थे है इसे subclass।

जय: बिल्कुल। यह ऑब्जेक्ट के पूरे लेआउट को बदल देगा, इसलिए हम चालें चलाने में सक्षम नहीं होंगे कि हम उस गति को गति देते हैं।

http://www.codeproject.com/KB/cs/expandSealed.aspx

तो, हाँ, अंतर्निहित ऑपरेटर अपने एकमात्र समाधान है:

यहाँ CodeProject लेख है कि आप शायद पहले देखा है है।

+0

'स्ट्रिंग' के बारे में जानकारी के लिए धन्यवाद, लेकिन यह सीधे प्रासंगिक नहीं है। –

+1

मुझे पता है :) यह सिर्फ मैं यह जानने का प्रयास करता हूं कि चीजें जो मुझे छीनती हैं वे जिस तरह से हैं। –

+0

कई बार 'स्ट्रिंग' जैसे किसी प्रकार से अर्ध-वारिस करने में सक्षम होना उपयोगी होगा, भले ही व्युत्पन्न प्रकार के अंतर्निहित वर्ग के किसी भी गैर-सार्वजनिक सदस्यों तक पहुंच न हो, न ही उसके किसी भी सदस्य को ओवरराइड करें, न ही कोई फ़ील्ड जोड़ें यदि इस तरह के प्रकार नए इंटरफेस जोड़ सकते हैं - भले ही उनके पास कोई सदस्य न हो, तो यह गहराई से अपरिवर्तनीय इंटरफेस जैसी चीजों को परिभाषित करने में मददगार हो सकता है (उदाहरण के लिए यदि कोई एक प्रकार 'डीपली इम्यूटेबल इन्ट' घोषित कर सकता है जो कि 'int' जैसा व्यवहार करता है लेकिन विरासत में 'IAmDeeplyImmutable', और इसी तरह अन्य अंतर्निर्मित प्रकारों के लिए भी ऐसा करते हैं, तो कोई भी ... – supercat

1

मुझे लगता है कि मुझे नहीं लगता कि आप एक ही समय में मजबूत प्रकार और अंतर्निहित स्ट्रिंग रूपांतरण क्यों चाहते हैं। मेरे लिए, एक दूसरे को बाहर नियम।

मैंने इनट्स के लिए एक ही समस्या को हल करने का प्रयास किया (आप शीर्षक में int का उल्लेख करते हैं, लेकिन सवाल में नहीं)। मैंने पाया कि एक enum घोषित करने से आपको एक प्रकार का सुरक्षित पूर्णांक मिलता है जिसे स्पष्ट रूप से/से int में डालने की आवश्यकता होती है।

अद्यतन

Enums इरादा खुला सेट के लिए नहीं हो सकता है, लेकिन अभी भी इस तरह से इस्तेमाल किया हो सकता है। यह नमूना एक डेटाबेस में कई तालिकाओं के आईडी कॉलम के बीच अंतर करना एक संकलन प्रयोग से है:

enum ProcID { Unassigned = 0 } 
    enum TenderID { Unassigned = 0 } 

    void Test() 
    { 
     ProcID p = 0; 
     TenderID t = 0; <-- 0 is assignable to every enum 
     p = (ProcID)3; <-- need to explicitly convert 

     if (p == t) <-- operator == cannot be applied 
      t = -1; <-- cannot implicitly convert 

     DoProc(p); 
     DoProc(t); <-- no overloaded method found 
     DoTender(t); 
    } 

    void DoProc(ProcID p) 
    { 
    } 

    void DoTender(TenderID t) 
    { 
    } 
+0

में रूपांतरण के समान परिस्थितियों में मेरा मतलब था 'दृढ़ता से टाइप किया गया' जैसा कि 'स्ट्रिंग' के अलावा अपना स्वयं का विशिष्ट प्रकार और सीधे विनिमय करने योग्य नहीं था। शब्द अधिभार के लिए माफ़ी :)। एनम्स 'int' मामले के लिए बहुत मदद नहीं करते हैं क्योंकि वे अपने दायरे को परिभाषित करते हैं और मामलों के खुले सेट (बनाम गणना मूल्यों का एक बंद सेट) पर उपयोग करने का इरादा नहीं रखते हैं। –

1

मुझे लगता है कि आप विस्तार तरीकों का उपयोग करना चाहते हैं। वे आपको एक नया व्युत्पन्न प्रकार बनाये बिना कक्षा की कार्यक्षमता बढ़ाने की अनुमति देते हैं।

+2

विस्तार विधियां आकर्षक होंगी यदि मैं विशिष्ट प्रकार के उपनाम बना सकता हूं और आधार 'स्ट्रिंग' प्रकार के बजाय उपनाम पर एक्सटेंशन विधि को परिभाषित कर सकता हूं। मैं चाहता हूं कि संकलक यह सुनिश्चित करने के लिए प्रकार की सुरक्षा जांच कर सके कि कोई गलती से किसी ईमेल एड्रेस को फ़ोन नम्बर में कॉपी करने की कोशिश नहीं करता है या ऐसा कुछ पागल/आकस्मिक है। –

2

ऐसा लगता है कि आपके पास कम से कम एक उचित सी # knoledgde है इसलिए मेरा जवाब बेवकूफ प्रतीत हो सकता है, लेकिन आप जो चाहते हैं उसे "टाइप पदानुक्रम" कहा जाता है और स्ट्रिंग क्लास को कोड करने वाले लोग आपको "ओओ फीचर" का उपयोग करने से रोकना चाहते थे। इसलिए उन्होंने स्ट्रिंग क्लास को सील कर दिया, यही कारण है कि आप जो भी चाहते हैं वह करने में सक्षम नहीं होंगे। सबसे अच्छा तरीका यह है कि आप अभी इस पर हैं: अपना स्वयं का प्रकार बनाएं और स्ट्रिंग में एक अंतर्निहित रूपांतरण करें।

0

मैंने इस वर्ग को समान आवश्यकताओं को कवर करने के लिए बनाया है। यह एक प्रकार "int" के लिए है (मैं भी "स्ट्रिंग" के लिए एक है):

public class NamedInt : IComparable<int>, IEquatable<int> 
{ 
    internal int Value { get; } 

    protected NamedInt() { } 
    protected NamedInt(int val) { Value = val; } 
    protected NamedInt(string val) { Value = Convert.ToInt32(val); } 

    public static implicit operator int (NamedInt val) { return val.Value; } 

    public static bool operator ==(NamedInt a, int b) { return a?.Value == b; } 
    public static bool operator ==(NamedInt a, NamedInt b) { return a?.Value == b?.Value; } 
    public static bool operator !=(NamedInt a, int b) { return !(a==b); } 
    public static bool operator !=(NamedInt a, NamedInt b) { return !(a==b); } 

    public bool Equals(int other) { return Equals(new NamedInt(other)); } 
    public override bool Equals(object other) { 
     if ((other.GetType() != GetType() && other.GetType() != typeof(string))) return false; 
     return Equals(new NamedInt(other.ToString())); 
    } 
    private bool Equals(NamedInt other) { 
     if (ReferenceEquals(null, other)) return false; 
     if (ReferenceEquals(this, other)) return true; 
     return Equals(Value, other.Value); 
    } 

    public int CompareTo(int other) { return Value - other; } 
    public int CompareTo(NamedInt other) { return Value - other.Value; } 

    public override int GetHashCode() { return Value.GetHashCode(); } 

    public override string ToString() { return Value.ToString(); } 
} 

और अपने मामले में यह उपभोग करने के लिए:

public class MyStronglyTypedInt: NamedInt { 
    public MyStronglyTypedInt(int value) : base(value) { 
     // Your validation can go here 
    } 
    public static implicit operator MyStronglyTypedInt(int value) { 
     return new MyStronglyTypedInt(value); 
    } 

    public bool Validate() { 
     // Your validation can go here 
    } 
} 

आप क्रमानुसार करने में सक्षम होने की जरूरत है यह (न्यूटनॉफ्ट.जेसन), मुझे बताएं और मैं कोड जोड़ दूंगा।