सी # में शब्दकोश के लिए शाब्दिक अंकन?


181

मेरे पास वर्तमान में जावास्क्रिप्ट के बीच एक WebSocket और C # में प्रोग्राम किया गया एक सर्वर है। जावास्क्रिप्ट में, मैं एक सहयोगी सरणी का उपयोग करके आसानी से डेटा पास कर सकता हूं:

var data = {'test': 'val',
            'test2': 'val2'};

सर्वर की ओर इस डेटा ऑब्जेक्ट का प्रतिनिधित्व करने के लिए, मैं एक का उपयोग करता हूं Dictionary<string, string>, लेकिन यह जावास्क्रिप्ट की तुलना में अधिक 'टाइपिंग-महंगा' है:

Dictionary<string, string> data = new Dictionary<string,string>();
data.Add("test", "val");
data.Add("test2", "val2");

क्या Dictionaryसी # में सहयोगी सरणियों / एस के लिए किसी प्रकार का शाब्दिक अंकन है?


C # 9 में डिक्शनरी लिटरल्स का प्रस्ताव है। मैं इसके बारे में नीचे एक उत्तर देता हूं । हमारा सपना सच हो गया!
aloisdg codidact.com

जवाबों:


291

आप संग्रह आरंभीकृत सिंटैक्स का उपयोग करते हैं , लेकिन आपको अभी भी एक new Dictionary<string, string>ऑब्जेक्ट बनाने की आवश्यकता है क्योंकि शॉर्टकट सिंटैक्स Add()कॉल के एक समूह में अनुवादित है (जैसे आपका कोड):

var data = new Dictionary<string, string>
{
    { "test", "val" }, 
    { "test2", "val2" }
};

C # 6 में, अब आपके पास शब्दकोश के साथ-साथ इंडेक्स का समर्थन करने वाले किसी अन्य प्रकार के साथ एक अधिक सहज वाक्यविन्यास का उपयोग करने का विकल्प है । उपरोक्त कथन को इस प्रकार लिखा जा सकता है:

var data = new Dictionary<string, string>
{
    ["test"] = "val",
    ["test2"] = "val2"
};

संग्रह initializers के विपरीत, यह एक उपयुक्त Add()विधि के बजाय, हुड के नीचे अनुक्रमणिका सेटर को आमंत्रित करता है ।


2
धन्यवाद। Dictionary<string, string>हालांकि यह एक को दूर करना संभव है ? यह बेमानी लगता है, लेकिन मैं गलत हो सकता है। संपादित करें: यह वास्तव में अधिक बेहतर तरीका लगता है, धन्यवाद।
pimvdb

3
@pimvdb: हाँ आप यह कर सकते हैं: इसे एक के रूप में घोषित करें var, कंपाइलर टाइप से अनुमान लगाएगा new। मैंने अपना उत्तर संपादित किया।
BoltClock

7
ध्यान दें कि यह शाब्दिक अंकन नहीं है, कड़ाई से बोल रहा है ... यह आरंभीकरण के लिए सिर्फ एक शॉर्टकट है। केवल स्ट्रिंग और कुछ आदिम प्रकारों का शाब्दिक प्रतिनिधित्व है
थॉमस लेवेस्क

यदि आप का अर्थ है कि आप "स्ट्रिंग" में से एक को हटाना चाहते हैं - तो वे निरर्थक नहीं हैं - एक कुंजी प्रकार के लिए है, दूसरा मूल्य प्रकार के लिए है। शब्दकोश के लिए कोई शाब्दिक विशिष्ट नहीं है, इस उत्तर में प्रयुक्त संकेतन एक जोड़ें विधि के साथ सभी वर्गों के लिए सामान्य है जो दो तार लेता है (और IEnumerable) को लागू करता है।
मार्कस जॉन्सन

1
@ मर्कस जॉनसन: उनका मतलब था, सचमुच Dictionary<string, string>। मेरे कोड ने मूल रूप से प्रकार घोषित किया, मैंने varउसकी टिप्पणी के बाद इसे बदल दिया था ।
BoltClock

13

हालांकि, शब्दकोश इनिशियलाइज़र उत्तर पूरी तरह से सही है, इस पर एक और दृष्टिकोण है जो मैं इंगित करता हूं (लेकिन मैं इसकी सिफारिश नहीं कर सकता हूं)। यदि आपका लक्ष्य ट्राइ एपीआई उपयोग प्रदान करना है, तो आप अनाम वस्तुओं का उपयोग कर सकते हैं।

var data = new { test1 = "val", test2 = "val2"};

"डेटा" वैरिएबल तब एक "अकथ्य" अनाम प्रकार का होता है, इसलिए आप इसे केवल इसी रूप में पास कर सकते हैं System.Object। आप तब कोड लिख सकते हैं जो एक अनाम वस्तु को एक शब्दकोश में बदल सकता है। ऐसा कोड प्रतिबिंब पर निर्भर करेगा, जो संभवतः धीमा होगा। हालाँकि, आप उपयोग कर सकते हैं System.Reflection.Emit, या System.Linq.Expressionsएक प्रतिनिधि को संकलित और कैश कर सकते हैं जो बाद की कॉल को बहुत तेज करेगा।

Asp.net MVC API इस तकनीक का उपयोग कई स्थानों पर करते हैं जो मैंने देखा है। बहुत सारे एचटीएमएल हेल्पर्स में ओवरलोड होते हैं जो किसी वस्तु या शब्दकोश को स्वीकार करते हैं। मुझे लगता है कि उनके एपीआई डिजाइन का लक्ष्य वही है जो आप बाद में हैं; विधि कॉल पर ट्रिक सिंटैक्स।


1
केवल तभी मदद मिलेगी जब कुंजी का सेट स्थिर होगा। आप एक ही उद्देश्य के लिए टुपल्स का उपयोग भी कर सकते हैं।
सेह

8

का उपयोग करते हुए DynamicObject, एक सरल शब्दकोश इनिशियलाइज़र बनाना मुश्किल नहीं है।

कल्पना करें कि आप निम्न विधि को कॉल करना चाहते हैं

void PrintDict(IDictionary<string, object> dict) {
    foreach(var kv in dict) {
        Console.WriteLine ("  -> " + kv.Key + " = " + kv.Value);
    }
}

जैसे एक शाब्दिक वाक्य रचना का उपयोग करना

var dict = Dict (Hello: "World", IAm: "a dictionary");
PrintDict (dict);

इस तरह एक गतिशील वस्तु बनाकर इसे पूरा किया जा सकता है

dynamic Dict {
    get {
        return new DynamicDictFactory ();
    }
}

private class DynamicDictFactory : DynamicObject
{
    public override bool TryInvoke (InvokeBinder binder, object[] args, out object result)
    {
        var res = new Dictionary<string, object> ();
        var names = binder.CallInfo.ArgumentNames;

        for (var i = 0; i < args.Length; i++) {
            var argName = names [i];
            if(string.IsNullOrEmpty(argName)) throw new ArgumentException();
            res [argName] = args [i];
        }
        result = res;
        return true;
    }
}

6

डिक्शनरी लिटरल्स का उपयोग करें (C # 9 प्रस्ताव)

सी # 9 Dictionary<TKey,TValue>शब्दकोश टाइप नाम या प्रकार के मापदंडों को निर्दिष्ट किए बिना आरंभिक वस्तुओं को बनाने के लिए एक सरल वाक्यविन्यास का परिचय देता है । शब्दकोष के प्रकार पैरामीटर को सरणी प्रकार के निष्कर्ष के लिए उपयोग किए गए मौजूदा नियमों का उपयोग करके अनुमान लगाया गया है।

// C# 1..8    
var x = new Dictionary <string,int> () { { "foo", 4 }, { "bar", 5 }};   
// C# 9    
var x = ["foo":4, "bar": 5];  

यह वाक्य रचना सी # सरल में शब्दकोशों के साथ काम करती है और अनावश्यक कोड को हटा देती है।

आप GitHub पर समस्या का अनुसरण कर सकते हैं (और यहाँ C # 9 के लिए मील का पत्थर है )।

संपादित करें: यह प्रस्ताव वर्तमान में अस्वीकार कर दिया गया है :

[...] हमें लगता है कि डेटा को इनिशियलाइज़ करने के इर्द-गिर्द कई दिलचस्प उपयोग के मामले हैं, विशेष रूप से अपरिवर्तनीय शब्दकोशों जैसी चीजों के लिए। हमें किसी शब्दकोश को आरंभ करने के लिए मौजूदा वाक्यविन्यास नहीं मिला है, न ही हम इसे कोड में एक अक्सर पैटर्न के रूप में देखते हैं जो एक भाषा सुविधा से बहुत लाभान्वित होगा। हम बात करते हैं कि डेटा को रिकॉर्ड करने के सामान्य क्षेत्र को रिकॉर्ड करने और वापस करने के बाद फिर से देखा जाना चाहिए। [...]


1
महान विचार, आशा है कि यह इसे बनाता है, ऐसा लगता है जैसे कोई
ब्रेनर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.