সি # তে একটি ধ্রুবক অভিধান তৈরি করা হচ্ছে


128

সবচেয়ে কার্যকর উপায় একটি তৈরি করতে কী ধ্রুবক (কখনও রানটাইম অংশে পরিবর্তন) এর ম্যাপিং strings করাint গুলি?

আমি একটি কনস্ট ডিকশনারি ব্যবহার করার চেষ্টা করেছি , কিন্তু এটি কার্যকর হয়নি।

আমি উপযুক্ত শব্দার্থবিজ্ঞান সহ একটি অপরিবর্তনীয় মোড়কে বাস্তবায়ন করতে পারি , তবে এটি এখনও পুরোপুরি সঠিক বলে মনে হয় না।


যারা জিজ্ঞাসা করেছেন তাদের জন্য, আমি উত্পাদিত শ্রেণিতে IDataErrorInfo বাস্তবায়ন করছি এবং আমার বর্ণনাকারীদের অ্যারেতে কলামের নাম অনুসন্ধান করার উপায় খুঁজছি।

আমি সচেতন ছিলাম না (পরীক্ষার সময় টাইপো! ডিও!) যা স্যুইচটি স্ট্রিং গ্রহণ করে, তাই এটিই আমি ব্যবহার করব। ধন্যবাদ!


1
: একটি সমাধান এখানে stackoverflow.com/questions/10066708/...

উত্তর:


180

সি # তে সত্যিকারের সংকলন-সময় উত্পন্ন ধ্রুবক অভিধান তৈরি করা সহজসাধ্য কাজ নয়। আসলে, এখানে উত্তরগুলির সত্যিকার অর্থে কোনওটিই তা অর্জন করে না।

যদিও আপনার প্রয়োজনগুলি পূরণ করে তবে একটি সমাধান রয়েছে, যদিও অগত্যা এটি একটি সুন্দর নয়; মনে রাখবেন যে সি # স্পেসিফিকেশন অনুসারে, স্যুইচ-কেস টেবিলগুলি ধ্রুব হ্যাশ জাম্প টেবিলগুলিতে সংকলিত হয়। এটি হ'ল এগুলি ধ্রুব অভিধান, যদি-অন্য বিবৃতিগুলির একটি সিরিজ না। সুতরাং এই মত একটি সুইচ-কেস স্টেটমেন্ট বিবেচনা করুন:

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

এটি আপনি চান ঠিক কি। এবং হ্যাঁ, আমি জানি, এটি কুরুচিপূর্ণ।


9
এটি যাইহোক উত্পন্ন কোড রয়েছে, ভাল পারফরম্যান্স বৈশিষ্ট্য রয়েছে, সংকলন-সময় গণনা করা যেতে পারে এবং আমার ব্যবহারের ক্ষেত্রেও অন্যান্য চমৎকার বৈশিষ্ট্য রয়েছে। আমি এইভাবে এটি করা হবে!
ডেভিড স্মিট

4
কেবল সতর্ক থাকুন যে অ-মূল্যমানের ধরণগুলি এমনকি এটির মতো ফিরিয়ে দেওয়া আপনার ক্লাসগুলি অনিবার্যতা ভেঙে দেয়।
টম অ্যান্ডারসন

35
স্যুইচ-কেস দুর্দান্ত হয়, যতক্ষণ না আপনার মানগুলির মাধ্যমে "ভবিষ্যতবাণী" করা দরকার।
অ্যালেক্স

6
এটিতে ডিকোরিয়ান্সগুলির অনেকগুলি সুন্দর ফাংশন নেই।
জিনান জিং

1
@ টমএন্ডারসন: প্রত্যাবর্তিত আইটেমগুলি মান ধরণের (পরিবর্তনীয় বা না), বা যদি তা পরিবর্তনযোগ্য শ্রেণীর অবজেক্ট হয় তবে কনস্ট্রাক্টটি অপরিবর্তনীয় আচরণ করবে।
সুপারক্যাট

37

বর্তমান কাঠামোয় মূল্যবান কয়েকটি স্থাবর সংগ্রহ রয়েছে। নেট .NET- এ একটি তুলনামূলক ব্যথা মুক্ত বিকল্পের কথা ভাবতে পারি:

ব্যবহার 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

এটি একটি "কনটেন্ট ডিকশনারি" এ আপনি পেতে পারেন এমন নিকটতম জিনিস:

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

সংকলকটি যথাসম্ভব পরিষ্কার কোড তৈরি করতে যথেষ্ট স্মার্ট হবে।


8

4.5+ ফ্রেমওয়ার্ক ব্যবহার করা হলে আমি কেবলমাত্র পাঠ্য ম্যাপিং / ধ্রুবকগুলি করতে ReadOnlyD शब्दकोয় (তালিকার জন্য কেবলমাত্র ReadOnly সংগ্রহ) ব্যবহার করব would এটি নিম্নলিখিত উপায়ে কার্যকর করা হয়েছে।

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";
    }
}

এখন আপনি .PareClass.FooD অভিধান.Key1, ইত্যাদি অ্যাক্সেস করতে পারেন


কারণ এটি IDataErrorInfo ইন্টারফেস প্রয়োগ করে না।
ডেভিড স্মিট

1

অভিধানগুলির জন্য কোনও মানক অপরিবর্তনীয় ইন্টারফেস বলে মনে হয় না, সুতরাং দুর্ভাগ্যক্রমে একটি মোড়ক তৈরি করা একমাত্র যুক্তিসঙ্গত বিকল্প বলে মনে হয়।

সম্পাদনা : মার্ক গ্র্যাভেল আইলুকআপটি পেয়েছি যা আমি মিস করেছি - এটি আপনাকে কমপক্ষে একটি নতুন মোড়ক তৈরি এড়াতে অনুমতি দেবে, যদিও আপনার এখনও ডিকশনারটি .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

আমি উইনফর্মস কম্বোবক্সের সাথে আবদ্ধ হওয়ার পর থেকে অন্য একটি ধারণা:

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
কারণ নির্দিষ্ট শর্তে উপলব্ধ বিকল্পগুলির তুলনায় এটি বেশ ব্যয়বহুল।
ডেভিড স্মিট

এটি এমনকি সংকলন করে না কারণ
অস্টিন ডাব্লু ব্রায়ান

@ অস্টিন ডাব্লু ব্রায়ান হ্যাঁ এটি সংকলন করেছেন
derHugo
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.