C # में एक निरंतर शब्दकोश बनाना


128

सबसे कारगर तरीका एक बनाने के लिए क्या है निरंतर (कभी नहीं कार्यावधि में बदल जाता है) की मैपिंग stringके लिए रों intरों?

मैंने एक कास्ट डिक्शनरी का उपयोग करने की कोशिश की है , लेकिन यह काम नहीं किया।

मैं उपयुक्त शब्दार्थ के साथ एक अपरिवर्तनीय आवरण को लागू कर सकता था , लेकिन यह अभी भी पूरी तरह से सही नहीं लगता है।


जिन लोगों ने पूछा है, मैं एक उत्पन्न वर्ग में IDataErrorInfo को लागू कर रहा हूं और मेरे विवरण के विवरणों में कॉलम नाम देखने का तरीका ढूंढ रहा हूं ।

मुझे पता नहीं था (टाइपो परीक्षण करते समय! डीओएच!) स्विच को स्वीकार करता है, इसलिए यही मैं उपयोग करने वाला हूं। धन्यवाद!


1
यहाँ एक समाधान है: stackoverflow.com/questions/10066708/…

जवाबों:


180

वास्तव में C # में एक निरंतर संकलन-समय उत्पन्न निरंतर शब्दकोश बनाना वास्तव में एक सीधा काम नहीं है। वास्तव में, यहां कोई भी उत्तर वास्तव में प्राप्त नहीं होता है।

हालांकि एक उपाय है जो आपकी आवश्यकताओं को पूरा करता है, हालांकि जरूरी नहीं कि यह एक अच्छा हो; याद रखें कि C # स्पेसिफिकेशन के अनुसार, स्विच-केस टेबल को लगातार हैश जंप टेबल में संकलित किया जाता है। यही है, वे निरंतर शब्दकोशों हैं, अगर-और कथनों की एक श्रृंखला नहीं है। तो इस तरह से स्विच-केस स्टेटमेंट पर विचार करें:

switch (myString)
{
   case "cat": return 0;
   case "dog": return 1;
   case "elephant": return 3;
}

यह वही है जो आप चाहते हैं। और हाँ, मुझे पता है, यह बदसूरत है।


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

4
बस ध्यान रखें कि गैर-प्रकार के रिटर्न, यहां तक ​​कि इस तरह से, आपकी कक्षाएं अपरिवर्तनीयता को तोड़ देगी।
टॉम एंडरसन

35
स्विच-केस कमाल है, जब तक आपको मूल्यों के माध्यम से "फ़ॉरच" करने की आवश्यकता नहीं है।
एलेक्स

6
इसमें बहुत सारे अच्छे कार्यों का अभाव है जो कि शब्दकोशों में हैं।
ज़िनन ज़िंग

1
@TomAnderson: यदि लौटाए गए आइटम प्रकार (म्यूटेबल या नहीं) हैं, या यदि वे अपरिवर्तनीय वर्ग ऑब्जेक्ट हैं, तो निर्माण अपरिवर्तनीय व्यवहार करेगा।
सुपरकैट

37

वर्तमान ढांचे में कीमती कुछ अपरिवर्तनीय संग्रह हैं। मैं .NET 3.5 में एक अपेक्षाकृत दर्द मुक्त विकल्प के बारे में सोच सकता हूं:

उपयोग Enumerable.ToLookup()- Lookup<,>वर्ग अपरिवर्तनीय है (लेकिन आरएच पर बहु-मूल्यवान है); आप इसे Dictionary<,>बहुत आसानी से कर सकते हैं:

    Dictionary<string, int> ids = new Dictionary<string, int> {
      {"abc",1}, {"def",2}, {"ghi",3}
    };
    ILookup<string, int> lookup = ids.ToLookup(x => x.Key, x => x.Value);
    int i = lookup["def"].Single();

15
enum Constants
{
    Abc = 1,
    Def = 2,
    Ghi = 3
}

...

int i = (int)Enum.Parse(typeof(Constants), "Def");

2
दिलचस्प विचार! मुझे आश्चर्य है कि पार्स () कॉल कितना अच्छा प्रदर्शन करता है। मुझे डर है कि केवल एक प्रोफाइलर जवाब दे सकता है।
डेविड श्मिट

10

यह आप "CONST Dictionary" के लिए निकटतम चीज़ है:

public static int GetValueByName(string name)
{
    switch (name)
    {
        case "bob": return 1;
        case "billy": return 2;
        default: return -1;
    }
}

कोड को यथासंभव साफ करने के लिए कंपाइलर काफी स्मार्ट होगा।


8

यदि 4.5+ फ्रेमवर्क का उपयोग करते हुए मैं रीडऑनली मैपिंग / स्थिरांक करने के लिए ReadOnlyDictionary (सूचियों के लिए ReadOnly संग्रह) का उपयोग करेगा। इसे निम्नलिखित तरीके से लागू किया गया है।

static class SomeClass
{
    static readonly ReadOnlyDictionary<string,int> SOME_MAPPING 
        = new ReadOnlyDictionary<string,int>(
            new Dictionary<string,int>()
            {
                { "One", 1 },
                { "Two", 2 }
            }
        )
}        

private static readonly Dictionary<string, string> _yourDictionaryName = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase) { { "One",1 }, { "Two",2 }, { "Three",3 }, };मैंने इस तरह से इसे किया।
संकट सोनवणे

@SanketSonavane एक के readonly Dictionary<TKey, TValue>बराबर नहीं है ReadOnlyDictionary<TKey, TValue>। वास्तव में, वे जिस तरह से "केवल पढ़े जाते हैं" एक दूसरे के बहुत विपरीत हैं। देखें: dotnetfiddle.net/v0l4aA
ब्रॉट्स वेम्ब

2

अपने मूल्यों को घोंसले बनाने के लिए नामस्थान या वर्गों का उपयोग क्यों नहीं करते? यह अपूर्ण हो सकता है, लेकिन यह बहुत साफ है।

public static class ParentClass
{
    // here is the "dictionary" class
    public static class FooDictionary
    {
        public const string Key1 = "somevalue";
        public const string Foobar = "fubar";
    }
}

अब आप एक्सेस कर सकते हैं ।ParentClass.FooDictionary.Key1, आदि।


क्योंकि यह IDataErrorInfo इंटरफ़ेस को लागू नहीं करता है।
डेविड श्मिट

1

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

संपादित करें : मार्क ग्रेवेल ने ILookup को पाया जो मैंने याद किया - जो आपको कम से कम एक नया आवरण बनाने से बचने की अनुमति देगा, हालांकि आपको अभी भी .ToLookup () के साथ शब्दकोश को बदलने की आवश्यकता है।

यदि यह एक विशिष्ट परिदृश्य के लिए विवश है, तो आप अधिक व्यावसायिक-तर्क-उन्मुख इंटरफ़ेस के साथ बेहतर हो सकते हैं:

interface IActiveUserCountProvider
{
    int GetMaxForServer(string serverName);
}

1

मुझे यकीन नहीं है कि किसी ने इसका उल्लेख नहीं किया है, लेकिन सी # में उन चीजों के लिए जो मैं कॉन्स्टेबल असाइन नहीं कर सकता हूं, मैं स्थैतिक केवल-पढ़ने के गुणों का उपयोग करता हूं।

उदाहरण:

public static readonly Dictionary<string, string[]> NewDictionary = new Dictionary<string, string[]>()
        {
            { "Reference1", Array1 },
            { "Reference2", Array2 },
            { "Reference3", Array3 },
            { "Reference4", Array4 },
            { "Reference5", Array5 }
        };

क्योंकि शब्दकोश की सामग्री अभी भी परिवर्तनशील है, और इसे रनटाइम पर आवंटित किया गया है।
डेविड श्मिट

0

बस एक और विचार के बाद से मैं एक winforms combobox के लिए बाध्य कर रहा हूँ:

public enum DateRange {
    [Display(Name = "None")]
    None = 0,
    [Display(Name = "Today")]
    Today = 1,
    [Display(Name = "Tomorrow")]
    Tomorrow = 2,
    [Display(Name = "Yesterday")]
    Yesterday = 3,
    [Display(Name = "Last 7 Days")]
    LastSeven = 4,
    [Display(Name = "Custom")]
    Custom = 99
    };

int something = (int)DateRange.None;

प्रदर्शन नाम से अंतर मान प्राप्त करने के लिए :

public static class EnumHelper<T>
{
    public static T GetValueFromName(string name)
    {
        var type = typeof(T);
        if (!type.IsEnum) throw new InvalidOperationException();

        foreach (var field in type.GetFields())
        {
            var attribute = Attribute.GetCustomAttribute(field,
                typeof(DisplayAttribute)) as DisplayAttribute;
            if (attribute != null)
            {
                if (attribute.Name == name)
                {
                    return (T)field.GetValue(null);
                }
            }
            else
            {
                if (field.Name == name)
                    return (T)field.GetValue(null);
            }
        }

        throw new ArgumentOutOfRangeException("name");
    }
}

उपयोग:

var z = (int)EnumHelper<DateRange>.GetValueFromName("Last 7 Days");

-2

क्यों नहीं:

public class MyClass
{
    private Dictionary<string, int> _myCollection = new Dictionary<string, int>() { { "A", 1 }, { "B", 2 }, { "C", 3 } };

    public IEnumerable<KeyValuePair<string,int>> MyCollection
    {
        get { return _myCollection.AsEnumerable<KeyValuePair<string, int>>(); }
    }
}

3
क्योंकि यह निर्दिष्ट शर्तों के तहत उपलब्ध विकल्पों की तुलना में काफी महंगा है।
डेविड श्मिट

क्योंकि यह भी संकलन नहीं करता है
AustinWBryan

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