2013-03-28 4 views
6

सबसे पहले, मेरे प्रश्न के बजाय मजेदार नाम बहाना। मैं कोई देशी वक्ता नहीं हूं और इन कुछ पात्रों में मेरे विचार व्यक्त करने में मुझे 10 मिनट लग गए।शब्दकोश सीमित संख्या के प्रकार

जो मैं करने की कोशिश कर रहा हूं वह सी # में एक शब्दकोश बनाना है जो मान को int, string या bool होने की अनुमति देता है। मेरे दिमाग में जो पहले आया था वह जेनेरिक का उपयोग कर रहा था, लेकिन जहां तक ​​मुझे पता है, मैं केवल एक प्रकार को संभावित मूल्य-प्रकार के रूप में परिभाषित कर सकता हूं, न कि "उनमें से एक बनें"। object का उपयोग करना भी संभव होगा, लेकिन मुक्केबाजी काफी प्रदर्शन-हत्यारा प्रतीत होता है।

क्या ऐसा करने का कोई तरीका है?

यहाँ क्या मेरे मन में आया है का एक नमूना है:

Dictionary<string, (string, int, bool)> foo = new Dictionary<string, (string, int, bool)>(); 
foo.Add("key1", "Hello, World!"); //Correct - Value is a string 
foo.Add("key2", 37); //Correct - Value is an int 
foo.Add("key3", true); //Correct - Value is a boolean 
foo.Add("key4", new Foobar()); //Compiler error - Value is a Foobar 

मेरे अंतिम लक्ष्य अन्य डेवलपर्स के लिए एक पुस्तकालय प्रदान करना है। इस सुविधा को उन्हें रनटाइम के दौरान "चर" परिभाषित करने और उन्हें एक प्रकार देने में सक्षम होना चाहिए।

संपादित करें: // फ़ायरफ़ॉक्स 'के बारे में: पेज config प्राप्त करने के लिए कुछ बहुत मैं क्या चाहते हैं उसके पास है

+2

मैंने आपका शीर्षक संपादित किया है। कृपया देखें, "[प्रश्नों में उनके शीर्षक में" टैग "शामिल होना चाहिए?] (Http://meta.stackexchange.com/questions/19190/)", जहां आम सहमति है "नहीं, उन्हें नहीं करना चाहिए"। –

+0

बहुत बहुत धन्यवाद। मैंने इसे अक्सर देखा है और सोचा कि यह सामान्य अभ्यास था। –

+0

कृपया टिप्पणी में शामिल लिंक को पढ़ें। यह एक अच्छा अभ्यास नहीं है, और जब मैं इसे देखता हूं तो मैं इसे ठीक करता हूं। –

उत्तर

6

करने के लिए अपने dictionry की सीमा को एक बिल्कुल नया वर्ग जो IDictionary लागू करता है और एक निजी चर के रूप में एक शब्दकोश का उपयोग करता क्यों नहीं बना।

फिर, ऐड तरीकों में, आप अपने खुद के तर्क प्रदान और उसके अनुसार असफल

नमूना कोड

public class MyDic : IDictionary<object, object> 
{ 
    private Dictionary<object, object> privateDic= new Dictionary<object,object>(); 


    public void Add(object key, object value) 
    { 
     if (value.GetType() == typeof(string)) 
      throw new ArgumentException(); 
     privateDic.Add(key, value); 
    } 
    //Rest of the interface follows 
} 
+3

इस कोड के बदले में कितना परिवर्तन होगा, आप 'ऐड' विधि के लिए 3 अलग ओवरलोड प्रदान कर सकते हैं, क्रमशः 'int', 'string', या' bool' टाइप 'मान को स्वीकार कर सकते हैं। ऐसा करके, टाइप समय पर नहीं, संकलन समय पर शुद्धता की जांच की जाती है। – dialer

+0

यह शायद जाने का सबसे अच्छा तरीका है। बहुत बहुत धन्यवाद –

+0

@dialer: आपके समाधान को स्पष्ट रूप से संकलन समय जांच का लाभ है। मुझे नहीं पता कि डेविड को इंजेक्शन प्रकारों और –

0

मैं सुझाव देना होगा:

  1. जैसे कि आपका शब्दकोश मूल्यों के लिए एक आधार प्रकार बनाएं MyDictionaryBaseType
  2. प्रत्येक मूल प्रकार के मान प्रकार के लिए इस मूल प्रकार को बढ़ाएं उदा। स्ट्रिंगडिक्शन टाइप: MyDictionaryBaseType, IntegerDictionryType: MyDictionaryBaseType ... आदि।
  3. MyDictionaryBaseType के साथ एक सामान्य शब्दकोश प्रकार बनाएं और इस बेस प्रकार को बढ़ाने के लिए प्रकार को सीमित करें।

इस तरह आप तीन specifed प्रकार

+0

क्या कोई यह बता सकता है कि यह क्यों कम किया गया था? –

+0

@ डेविडस्टॉकिंगर मुझे लगता है क्योंकि यह आपको काम करने के लिए 'int',' bool' और 'string' के लिए अपने स्वयं के प्रकार बनाने के लिए मजबूर करेगा। सैद्धांतिक रूप से (यानी इसके अलावा), यह एक बहुत अच्छा और साफ समाधान है। – dialer

0

आप इस तरह आवरण classs में मान डाल सकते हैं कर सकते हैं:

class Value 
{ 
} 

class TypedValue<T> : Value 
{ 
    public T Val; 
} 

class IntValue : TypedValue<int> 
{ 
} 

class StringValue : TypedValue<string> 
{ 
} 

class BoolValue : TypedValue<bool> 
{ 
} 

Dictionary<string,Value> foo; 

foo.Add("key1", new StringValue{Val="Hello World!"}); 

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

0

जो आप पूरा करने की कोशिश कर रहे हैं वह टाइप-सुरक्षित नहीं है जैसा कि यह खड़ा है। उदाहरण के लिए, मान लीजिए कि आप इस तरह के एक शब्दकोश डालते हैं:

var foo = new Dictionary<string, (string, int, bool)>(); 
var x = foo["key1"]; 
// What type is x? How could the compiler know? 

एक विचार एक कंटेनर वर्ग जो एक के दोनों string, int, या bool धारण कर सकते हैं विकसित करने में किया जाएगा।

public class StringIntBool { 
    private bool _isSet; 
    private bool _isString; 
    public bool IsString { 
     get { return _isString; } 
    } 
    // ... 

    private string _innerString; 
    public string InnerString { 
     get { 
      return _innerString; 
     } 
     set { 
      if (_isSet) { 
       throw new Exception("StringIntBool is already set"); 
      } 
      _isSet = true; 
      _isString = true; 
      _innerString = value; 
     } 
    } 

    // etc... 
} 

यह काफी बदसूरत है, और वास्तव में कई लाभ नहीं देता है।

एक विकल्प के रूप में, आप वास्तव में सभी तीन मानों को object एस के रूप में स्टोर कर सकते हैं, और फिर पैटर्न-मिलान करने के लिए Functional C# जैसी तकनीक/लाइब्रेरी का उपयोग करें, जैसे कई कार्यात्मक भाषाएं।

object x = "str"; 
int res = x.Match() 
    .With<string>(s => s == "str" ? 10 : 20) 
    .With<int>(i => i) 
    .With<bool>(b => b ? 50 : 60) 
    .Return<int>(); 

प्रोग्रामिंग का यह पैटर्न वास्तव में कुछ कार्यात्मक भाषा में काफी आम है। उदाहरण के लिए, एसएमएल में, आप डेटाटाइप को परिभाषित कर सकते हैं, और फिर आवश्यकतानुसार पैटर्न-मिलान कर सकते हैं।

(* StringIntBool *) 
datatype sib = SibString of string | SibInt of int | SibBool of bool 

val x = (* some instance of sib *) 
val y = case x of 
    SibString s => if s = "hello" then 50 else -50 
    | SibInt i => i 
    | SibBool b => if b then 10 else 20 
+0

जैसे रनटाइम की जांच की आवश्यकता है, मुझे लगता है कि आप F # में भेदभाव वाले संघों के साथ एक ही चीज़ कम या कम कर सकते हैं (मुझे पता है कि यह प्रश्न सी # के बारे में है) – JerKimball

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