একটি এনামকে অন্য ধরণের এনামে রূপান্তর করুন


120

আমি উদাহরণস্বরূপ ' Gender' ( Male =0 , Female =1) এর একটি এনাম পেয়েছি এবং আমার একটি পরিষেবা থেকে অন্য একটি এনাম রয়েছে যার নিজস্ব জেন্ডার এনাম রয়েছে ( Male =0 , Female =1, Unknown =2)

আমার প্রশ্ন হ'ল আমি কীভাবে তাদের এনাম থেকে আমার রূপান্তর করতে দ্রুত এবং সুন্দর কিছু লিখতে পারি?


6
আপনি "অজানা" কে রূপান্তর করতে চান?
পাভেল মিনায়েভ

উভয়ই একই মান থাকলে আপনি এনামকে অন্য এনাম প্রকারে
এস

উত্তর:


87

ন্যাটের প্রস্তাবিত দুটি রূপান্তর পদ্ধতি ব্যবহার করার সময় একটি এক্সটেনশন পদ্ধতি ব্যবহার করা বেশ ঝরঝরেভাবে কাজ করে:

public static class TheirGenderExtensions
{
    public static MyGender ToMyGender(this TheirGender value)
    {
        // insert switch statement here
    }
}

public static class MyGenderExtensions
{
    public static TheirGender ToTheirGender(this MyGender value)
    {
        // insert switch statement here
    }
}

স্পষ্টতই যদি আপনি না চান তবে আলাদা ক্লাস ব্যবহার করার দরকার নেই। আমার অগ্রাধিকার হ'ল বর্ধিত পদ্ধতিগুলি শ্রেণি / কাঠামো / এনুমিনেশনগুলিতে তারা প্রয়োগ করে এমনভাবে গোষ্ঠীভুক্ত করা।


233

প্রদত্ত Enum1 value = ..., তবে আপনি যদি নামটি বোঝাতে চান:

Enum2 value2 = (Enum2) Enum.Parse(typeof(Enum2), value.ToString());

যদি আপনি সংখ্যার মান দ্বারা বোঝাতে চান তবে আপনি সাধারণত খালি কাস্ট করতে পারেন:

Enum2 value2 = (Enum2)value;

(theালাই সহ, আপনি Enum.IsDefinedবৈধ মানগুলি পরীক্ষা করতে ব্যবহার করতে পারেন , যদিও)


16
এটি আরও ভাল উত্তর
নিকোলাস

1
এখানে এমন একটি সংস্করণ রয়েছে যা ব্যবহার করে Enum.Tryparse: Enum2 value2 = Enum.TryParse(value.ToString(), out Enum2 outValue) ? outValue : Enum2.Unknown; এটি আপনাকে ইনপুট মানগুলি হ্যান্ডেল করার অনুমতি দেবে যা Enum2কল করে Enum.IsDefinedবা ArgumentExceptionছুঁড়ে মারার প্রয়োজন ছাড়াই বিদ্যমান Enum.Parse। নোট করুন যে পরামিতিগুলির ক্রমটি কমবেশি থেকে বিপরীত Enum.Parse
স্যান্ডার

47

কেবলমাত্র একটিতে অন্তর্ভুক্ত করুন এবং তারপরে এটি অন্য এনামে কাস্ট করুন (বিবেচনা করে আপনি মানটির ভিত্তিতে ম্যাপিংটি করতে চান):

Gender2 gender2 = (Gender2)((int)gender1);

3
যদিও এটি 'বন্যে "দেখা অসম্ভব, এবং এটি জেন্ডারদের ক্ষেত্রে হওয়ার সম্ভাবনা খুব কম, তবে সেখানে এমন কিছু এনামের উপস্থিতি থাকতে পারে যা একটি long(বা ulong) দ্বারা সমর্থিত intরয়েছে যার পরিবর্তে সদস্যরা উপরে int.MaxValue(বা নীচে) সংজ্ঞায়িত রয়েছে int.MinValue), যার ক্ষেত্রে কাস্টটি intউপচে পড়তে পারে এবং আপনি সংজ্ঞায়িত হওয়া উচিত এমন একটি অনির্ধারিত এনাম মান দিয়ে শেষ করবেন।
ধনী ও'কেলি

অবশ্যই. সঠিক উপায়টি হবে (জেন্ডার 2) (এখানে অন্তর্নিহিত ধরণের সন্নিবেশ করান) জেন্ডার 1) তবে আমি মনে করি উপরের উদাহরণটি সঠিক ধারণা দেয় যাতে আমি এটি পরিবর্তন করব না।
অ্যাড্রিয়ান জানেস্কু

3
এর জন্য দুটি এনামের একই ক্রমে একই মান হওয়া প্রয়োজন। যদিও এটি এই নির্দিষ্ট সমস্যাটি সমাধান করে, এটি সত্যিই ভঙ্গুর এবং আমি সাধারণভাবে এনাম ম্যাপিংয়ের জন্য এটি ব্যবহার করব না।
Sonicblis

2
ভাল duh! । কোনও কিছুর উপর ভিত্তি করে ম্যাপিং করা দরকার। এই ক্ষেত্রে ম্যাপিং অবিচ্ছেদ্য মান হয়। নামের ভিত্তিতে ম্যাপিংয়ের জন্য আপনার আলাদা কোড দরকার। অন্য কিছু ম্যাপিংয়ের জন্য। নুন বলেছিলেন এটি "সাধারণভাবে এনাম ম্যাপিংয়ের জন্য" এবং আপনি যদি "সাধারণভাবে ম্যাপিং" এর অর্থ কী তা নির্দিষ্ট করে চেষ্টা না করতে পারেন তবে এই মামলাটির অস্তিত্ব নেই
অ্যাড্রিয়ান জানেস্কু

20

পুঙ্খানুপুঙ্খভাবে লেখার জন্য আমি সাধারণত একজোড়া ফাংশন তৈরি করি, একটি যা এনাম 1 নেয় এবং এনুম 2 এবং অন্যটি এনাম 2 নেয় এবং এনামকে 1 ফেরত দেয় প্রতিটি প্রতি ক্ষেত্রে কেস স্টেটমেন্ট ম্যাপিং ইনপুটগুলিকে আউটপুটগুলিতে নিয়ে আসে এবং ডিফল্ট কেসটি একটি ব্যতিক্রম ছুঁড়ে ফেলেছে অপ্রত্যাশিত মান সম্পর্কে অভিযোগ বার্তা।

এই বিশেষ ক্ষেত্রে আপনি এই বিষয়টি গ্রহণ করতে পারেন যে পুরুষ ও স্ত্রীলোকের পূর্ণসংখ্যার মান একই, তবে আমি এড়াতে পারব কারণ এটি হ্যাকিশ এবং ভাঙ্গনের শিকার হতে পারে যদি ভবিষ্যতে কোনও পরিবর্তন হয়।


7
+1 আমি অনেক বিকাশকারীকে এ্যামগুলিতে রূপান্তর করতে পূর্ণসংখ্যার মান ব্যবহার করার তাগিদ ছাড়তে দেখেছি তবে এটি অত্যন্ত ত্রুটিযুক্ত। 2 টি ফাংশন লেখার পুরানো স্কুল পদ্ধতি সময়ের সাথে সাথে এর মূল্য প্রমাণ করেছে ...
প্রমানকে হেমন্ত

20

যদি আমাদের থাকে:

enum Gender
{
    M = 0,
    F = 1,
    U = 2
}

এবং

enum Gender2
{
    Male = 0,
    Female = 1,
    Unknown = 2
}

আমরা নিরাপদে করতে পারি

var gender = Gender.M;
var gender2   = (Gender2)(int)gender;

অথবা এমনকি

var enumOfGender2Type = (Gender2)0;

আপনি যদি কেসটি আবরণ করতে চান যেখানে '=' চিহ্নের ডানদিকে একটি এনামের বাম পাশের এনামের চেয়ে বেশি মান রয়েছে - অন্যদের পরামর্শ অনুসারে আপনাকে নিজের পদ্ধতি / অভিধান লিখতে হবে।


আপনার উত্তর একটি প্রশ্ন জিজ্ঞাসার মত !? যদি হ্যাঁ এটি কোনও উত্তর নয় এবং যদি উপরে কোনও অনুরূপ উত্তর না থাকে ;)।
shA.t

13

আপনি এই জাতীয় একটি সাধারণ জেনেরিক এক্সটেনশন পদ্ধতি লিখতে পারেন

public static T ConvertTo<T>(this object value)            
    where T : struct,IConvertible
{
    var sourceType = value.GetType();
    if (!sourceType.IsEnum)
        throw new ArgumentException("Source type is not enum");
    if (!typeof(T).IsEnum)
        throw new ArgumentException("Destination type is not enum");
    return (T)Enum.Parse(typeof(T), value.ToString());
}

1
এটি উপরের উত্তরের পরামর্শ অনুসারে অনুপস্থিত মানগুলির ক্ষেত্রে কভার করে না। আপনারও এই কেসটি কভার করে এই এক্সটেনশন পদ্ধতিটি পরিবর্তন করা উচিত।
eRaisedToX

8

আপনি নিম্নলিখিত মত একটি সাধারণ ফাংশন লিখতে পারে:

public static MyGender ConvertTo(TheirGender theirGender)
{
    switch(theirGender)
    {
        case TheirGender.Male:
            break;//return male
        case TheirGender.Female:
            break;//return female
        case TheirGender.Unknown:
            break;//return whatever
    }
}

1
এটি কোনও ফাংশন নয়। প্রত্যাশিত 'মাইজেন্ডার' এবং আপনি 'অকার্যকর' প্রত্যাবর্তন করছেন
bl4ckr0se

7

কেউ আগ্রহী হলে এখানে একটি এক্সটেনশন পদ্ধতির সংস্করণ

public static TEnum ConvertEnum<TEnum >(this Enum source)
    {
        return (TEnum)Enum.Parse(typeof(TEnum), source.ToString(), true);
    }

// Usage
NewEnumType newEnum = oldEnumVar.ConvertEnum<NewEnumType>();

এর অর্থ কি বোঝা যাচ্ছে না যে উভয় গণনার একই সংখ্যাসূচক মান রয়েছে?
kuskmen

1
না, এটি স্ট্রিং দ্বারা নামে রূপান্তরিত হয়। সুতরাং এনাম.ফু (1) তাদের সংখ্যাসূচক মান পৃথক হলেও এনাম 2.ফু (2) এ অনুবাদ করবে।
জাস্টিন

3
public static TEnum ConvertByName<TEnum>(this Enum source, bool ignoreCase = false) where TEnum : struct
{
    // if limited by lack of generic enum constraint
    if (!typeof(TEnum).IsEnum)
    {
        throw new InvalidOperationException("enumeration type required.");
    }

    TEnum result;
    if (!Enum.TryParse(source.ToString(), ignoreCase, out result))
    {
        throw new Exception("conversion failure.");
    }

    return result;
}

2

আমি কিছুক্ষণ আগে একটি সেট এক্সটেনশন পদ্ধতি লিখেছিলাম যা বিভিন্ন ধরণের Enumএস এর জন্য কাজ করে । আপনি যেটি সাধন করতে চেষ্টা করছেন তার জন্য বিশেষত একটি কাজ Enumকরে FlagsAttributeএবং পাশাপাশি Enumবিভিন্ন অন্তর্নিহিত ধরণের সাথে পরিচালনা করে।

public static tEnum SetFlags<tEnum>(this Enum e, tEnum flags, bool set, bool typeCheck = true) where tEnum : IComparable
{
    if (typeCheck)
    {
        if (e.GetType() != flags.GetType())
            throw new ArgumentException("Argument is not the same type as this instance.", "flags");
    }

    var flagsUnderlyingType = Enum.GetUnderlyingType(typeof(tEnum));

    var firstNum = Convert.ToUInt32(e);
    var secondNum = Convert.ToUInt32(flags);

    if (set)
        firstNum |= secondNum;

    else
        firstNum &= ~secondNum;

    var newValue = (tEnum)Convert.ChangeType(firstNum, flagsUnderlyingType);

    if (!typeCheck)
    {
        var values = Enum.GetValues(typeof(tEnum));
        var lastValue = (tEnum)values.GetValue(values.Length - 1);

        if (newValue.CompareTo(lastValue) > 0)
            return lastValue;
    }

    return newValue;
}

সেখান থেকে আপনি আরও নির্দিষ্ট নির্দিষ্ট এক্সটেনশন পদ্ধতি যুক্ত করতে পারেন।

public static tEnum AddFlags<tEnum>(this Enum e, tEnum flags) where tEnum : IComparable
{
    SetFlags(e, flags, true);
}

public static tEnum RemoveFlags<tEnum>(this Enum e, tEnum flags) where tEnum : IComparable
{
    SetFlags(e, flags, false);
}

আপনি যেভাবে Enumচেষ্টা করার চেষ্টা করছেন তার মতো এটির ধরণের পরিবর্তন হবে।

public static tEnum ChangeType<tEnum>(this Enum e) where tEnum : IComparable
{
    return SetFlags(e, default(tEnum), true, false);
}

সতর্কতা অবলম্বন করুন, যদিও আপনি এই পদ্ধতিটি ব্যবহার করে যে কোনও Enumএবং যে কোনওর মধ্যে রূপান্তর করতে পারেন Enum, এমনকি পতাকা নেই those উদাহরণ স্বরূপ:

public enum Turtle
{
    None = 0,
    Pink,
    Green,
    Blue,
    Black,
    Yellow
}

[Flags]
public enum WriteAccess : short
{
   None = 0,
   Read = 1,
   Write = 2,
   ReadWrite = 3
}

static void Main(string[] args)
{
    WriteAccess access = WriteAccess.ReadWrite;
    Turtle turtle = access.ChangeType<Turtle>();
}

ভেরিয়েবলের মান turtleহবে Turtle.Blue

তবে Enumএই পদ্ধতিটি ব্যবহার করে অপরিজ্ঞাত মান থেকে সুরক্ষা পাওয়া যায় । এই ক্ষেত্রে:

static void Main(string[] args)
{
    Turtle turtle = Turtle.Yellow;
    WriteAccess access = turtle.ChangeType<WriteAccess>();
}

এই ক্ষেত্রে, accessসেট করা হবে WriteAccess.ReadWrite, যেহেতুWriteAccess Enum সর্বোচ্চ মূল্য 3 হয়।

Enumএর সাথে এর মিশ্রণের আর একটি পার্শ্বপ্রতিক্রিয়া FlagsAttributeএবং এটি ব্যতীত হ'ল রূপান্তর প্রক্রিয়াটি তাদের মানগুলির মধ্যে 1 থেকে 1 টি মিলবে না।

public enum Letters
{
    None = 0,
    A,
    B,
    C,
    D,
    E,
    F,
    G,
    H
}

[Flags]
public enum Flavors
{
    None = 0,
    Cherry = 1,
    Grape = 2,
    Orange = 4,
    Peach = 8
}

static void Main(string[] args)
{
    Flavors flavors = Flavors.Peach;
    Letters letters = flavors.ChangeType<Letters>();
}

এই ক্ষেত্রে, lettersএকটি মান থাকবে Letters.Hপরিবর্তে Letters.D, যেহেতু সমর্থন মান Flavors.Peach8. এছাড়াও থেকে একটি রূপান্তর, Flavors.Cherry | Flavors.Grapeকরতে Lettersউত্পাদ হবে Letters.C, যা unintuitive মনে করতে পারেন।


2

উপরের জাস্টিনের উত্তরের ভিত্তিতে আমি এটি নিয়ে এসেছি:

    /// <summary>
    /// Converts Enum Value to different Enum Value (by Value Name) See https://stackoverflow.com/a/31993512/6500501.
    /// </summary>
    /// <typeparam name="TEnum">The type of the enum to convert to.</typeparam>
    /// <param name="source">The source enum to convert from.</param>
    /// <returns></returns>
    /// <exception cref="InvalidOperationException"></exception>
    public static TEnum ConvertTo<TEnum>(this Enum source)
    {
        try
        {
            return (TEnum) Enum.Parse(typeof(TEnum), source.ToString(), ignoreCase: true);
        }
        catch (ArgumentException aex)
        {
            throw new InvalidOperationException
            (
                $"Could not convert {source.GetType().ToString()} [{source.ToString()}] to {typeof(TEnum).ToString()}", aex
            );
        }
    }

1

আমি জানি এটি একটি পুরানো প্রশ্ন এবং এর অনেকগুলি উত্তর রয়েছে, তবে আমি দেখতে পেয়েছি যে স্বীকৃত উত্তরের মতো একটি স্যুইচ স্টেটমেন্ট ব্যবহার করা কিছুটা জটিল, তাই এখানে আমার 2 সেন্ট রয়েছে:

আমার ব্যক্তিগত পছন্দের পদ্ধতিটি হচ্ছে একটি অভিধান ব্যবহার করা, যেখানে কীটি হ'ল উত্স এনুম এবং মান হ'ল লক্ষ্য এনুম - সুতরাং প্রশ্নটিতে উপস্থাপিত ক্ষেত্রে আমার কোডটি দেখতে এই রকম হবে:

var genderTranslator = new Dictionary<TheirGender, MyGender>();
genderTranslator.Add(TheirGender.Male, MyGender.Male);
genderTranslator.Add(TheirGender.Female, MyGender.Female);
genderTranslator.Add(TheirGender.Unknown, MyGender.Unknown);

// translate their to mine    
var myValue = genderTranslator[TheirValue];

// translate mine to their
var TheirValue = genderTranslator .FirstOrDefault(x => x.Value == myValue).Key;;

অবশ্যই, এটি একটি স্ট্যাটিক শ্রেণিতে আবৃত করা যেতে পারে এবং এটি একটি এক্সটেনশন পদ্ধতি হিসাবে ব্যবহার করা যেতে পারে:

public static class EnumTranslator
{

    private static Dictionary<TheirGender, MyGender> GenderTranslator = InitializeGenderTranslator();

    private static Dictionary<TheirGender, MyGender> InitializeGenderTranslator()
    {
        var translator = new Dictionary<TheirGender, MyGender>();
        translator.Add(TheirGender.Male, MyGender.Male);
        translator.Add(TheirGender.Female, MyGender.Female);
        translator.Add(TheirGender.Unknown, MyGender.Unknown);
        return translator;
    }

    public static MyGender Translate(this TheirGender theirValue)
    {
        return GenderTranslator[theirValue];
    }

    public static TheirGender Translate(this MyGender myValue)
    {
        return GenderTranslator.FirstOrDefault(x => x.Value == myValue).Key;
    }

}

আমি এই পদ্ধতির পছন্দ করি কারণ আপনি অভিধানটি পপুল করার জন্য উভয় অঙ্কটিও গণনা করতে পারেন। (যখন তারা অবশ্যই একই ক্রমে থাকে)
অ্যালেক্সএস

0

প্রথম এনামকে এর নামে রূপান্তর করতে আপনি টসস্ট্রিং () ব্যবহার করতে পারেন এবং তারপরে স্ট্রিংটিকে অন্য এনামে রূপান্তর করতে এনাম.পার্স () ব্যবহার করতে পারেন। মানটি গন্তব্য এনাম দ্বারা সমর্থিত না হলে এটি একটি ব্যতিক্রম ছুঁড়ে ফেলবে (উদাহরণস্বরূপ "অজানা" মানের জন্য)

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