এনাম "উত্তরাধিকার"


391

নিম্ন স্তরের নেমস্পেসে আমার একটি এনাম রয়েছে। আমি মধ্য স্তরের নেমস্পেসে এমন একটি শ্রেণি বা এনাম সরবরাহ করতে চাই যা নিম্ন স্তরের এনামগুলিকে "উত্তরাধিকার সূত্রে" দেয়।

namespace low
{
   public enum base
   {
      x, y, z
   }
}

namespace mid
{
   public enum consume : low.base
   {
   }
}

আমি আশাবাদী যে এটি সম্ভব, বা সম্ভবত এমন কোনও শ্রেণি যা এনামের স্থান গ্রহণ করতে পারে যা এনামের জন্য বিমূর্ততার একটি স্তর সরবরাহ করবে, তবে এখনও এই শ্রেণীর একটি উদাহরণ এনামকে অ্যাক্সেস দেয়।

থটস?

সম্পাদনা: আমি ক্লাসে কনস্টগুলিতে কেবল এটি পরিবর্তন না করানোর একটি কারণ হ'ল নিম্ন স্তরের এনামের একটি পরিষেবা প্রয়োজন যা আমার অবশ্যই গ্রহণ করা উচিত। আমাকে ডাব্লুএসডিএল এবং এক্সএসডি দেওয়া হয়েছে, যা কাঠামোটিকে এনাম হিসাবে সংজ্ঞায়িত করে। পরিষেবাটি পরিবর্তন করা যায় না।


উত্তর:


462

সপ্তাহের দিন. এনামগুলি অন্য এনাম থেকে উত্তরাধিকারী হতে পারে না। প্রকৃতপক্ষে সমস্ত এনামকে অবশ্যই উত্তরাধিকার সূত্রে উত্তরাধিকার সূত্রে উত্তরাধিকারী হতে হবে System.Enum। সি # সিন্টেক্সকে এনাম মানগুলির অন্তর্নিহিত প্রতিনিধিত্বকে পরিবর্তনের অনুমতি দেয় যা উত্তরাধিকার বলে মনে হয় তবে বাস্তবে তারা এখনও System.enum থেকে উত্তরাধিকারী হয়।

সম্পূর্ণ বিবরণের জন্য সিএলআই স্পেসের 8.5.2 বিভাগ দেখুন । অনুমান থেকে সম্পর্কিত তথ্য

  • সমস্ত enums থেকে প্রাপ্ত করা আবশ্যক System.Enum
  • উপরের কারণে, সমস্ত এনামগুলি মান ধরণের এবং তাই সিল করে

2
এবং সমস্ত মানের ধরণের সিস্টেম.ভ্যালু টাইপ থেকে প্রাপ্ত
রাজ মেগ্রেলিডজে

4
: যে @Seven এর উত্তর একটি বৈধ কার্যসংক্রান্ত নেই উল্লেখ আছে stackoverflow.com/a/4042826/538387
Tohid

তবে @ স্টিভেনের উত্তর switchপরিস্থিতি হিসাবে ব্যবহার করতে পারে না ।
zionpi

@ জিয়নপি হ্যাঁ তবে মনে রাখবেন যে (আমি বিশ্বাস করি) স্ট্যান্ডার্ড সুইচটি পুরো হিসাবে একই আইএল কোডে সংকলিত হয়ে যায়, অন্যথায় যদি, অন্য কোনও ব্লক করত: যা আমার মনে হয় যে আরও ভাল সিনট্যাক্স আছে। আপনি পুনরায় ভাগ করা / ভিএসের সমস্ত কেস স্টেটমেন্ট স্বয়ংক্রিয়ভাবে সম্পূর্ণ করার জন্য আলগা দক্ষতা অর্জন করেছেন, তবে আমি মনে করি এটি পৃথিবীর শেষ নয়। এটি ব্যক্তিগত পছন্দ তবে আমি সুইচ স্টেটমেন্টের ভক্ত নই।
মেমডেভোপার

165

আপনি ক্লাসগুলির সাথে যা চান তা অর্জন করতে পারেন:

public class Base
{
    public const int A = 1;
    public const int B = 2;
    public const int C = 3;
}
public class Consume : Base
{
    public const int D = 4;
    public const int E = 5;
}

এখন আপনি এই ক্লাসগুলি যেমন এনামগুলির মতো ব্যবহার করতে পারেন:

int i = Consume.B;

আপডেট (আপনার প্রশ্নের আপডেটের পরে):

যদি আপনি বিদ্যমান এনামে সংজ্ঞায়িত হিসাবে ধ্রুবকগুলিকে একই ইনট মানগুলি অর্পণ করেন তবে আপনি এনাম এবং ধ্রুবকের মধ্যে কাস্ট করতে পারেন, যেমন:

public enum SomeEnum // this is the existing enum (from WSDL)
{
    A = 1,
    B = 2,
    ...
}
public class Base
{
    public const int A = (int)SomeEnum.A;
    //...
}
public class Consume : Base
{
    public const int D = 4;
    public const int E = 5;
}

// where you have to use the enum, use a cast:
SomeEnum e = (SomeEnum)Consume.B;

8
আপনি তখন এই শ্রেণীর ক্ষেত্রগুলি কীভাবে গণনা করবেন? আমার জন্য এটি একটি এনামের গুরুত্বপূর্ণ আচরণ:Enum.GetValues(typeof(MyEnum)
মাইক ডি ক্লার্ক

1
আপনি প্রতিবিম্বটি ব্যবহার করতে পারেন: void Test() { foreach (System.Reflection.PropertyInfo pi in typeof(Consume).GetProperties()) { Console.WriteLine(pi.Name); } }
মনিয়েটো

2
প্রতিবিম্ব সহ সম্পত্তি সংগ্রহ করা উত্তরাধিকারসূত্রে প্রাপ্ত বস্তুর বৈশিষ্ট্যগুলিকে উপেক্ষা করে তা নিশ্চিত করা দরকার।
রবার্ট

প্রতিচ্ছবি সেই কাজের জন্য অত্যন্ত কুশ্রী।
dylanh724

1
প্রতিবিম্বটি ব্যবহার করার দরকার নেই, কোডেপ্রজেক্ট / আর্টিকেলস /২০৮০৫ / এনহানসিং- সি- এনিমামে বাস্তবায়ন এটি করার একটি ভাল উপায়, অবজেক্ট তৈরি হওয়ার সাথে সাথে তারা একটি তালিকায় যুক্ত হয় এবং সেই তালিকাটি ব্যবহার করা যেতে পারে অবজেক্টের ধরণের একটি তালিকা ফেরত দিন। আপনি যখন এটি উত্তরাধিকারের সাথে মিশ্রিত করবেন তখন আপনাকে নিশ্চিত করতে হবে যে আপনি উত্তরাধিকারী শ্রেণীর জন্য সঠিক তালিকাটি ব্যবহার করছেন।
পিবিও

112

সংক্ষিপ্ত উত্তর হলো 'না'। আপনি চাইলে কিছুটা খেলতে পারেন:

আপনি সর্বদা এরকম কিছু করতে পারেন:

private enum Base
{
    A,
    B,
    C
}

private enum Consume
{
    A = Base.A,
    B = Base.B,
    C = Base.C,
    D,
    E
}

তবে, এটি এত দুর্দান্ত কাজ করে না কারণ বেস.এ! = গ্রাহ্য.আ.

আপনি সর্বদা এরকম কিছু করতে পারেন, যদিও:

public static class Extensions
{
    public static T As<T>(this Consume c) where T : struct
    {
        return (T)System.Enum.Parse(typeof(T), c.ToString(), false);
    }
}

বেস এবং কনসুমের মধ্যে ক্রস করার জন্য ...

আপনি enums হিসাবে enums এর মান নিক্ষেপ করতে পারেন, এবং তাদের enum পরিবর্তে ints হিসাবে তুলনা করতে পারেন, কিন্তু এই ধরণের খুব sucks।

এক্সটেনশন পদ্ধতির রিটার্নে এটি টাইপ করা উচিত টি টাইপ করুন।


4
আমি এই খনন, মানুষ। এই ধারণাটি আমার ওআরএম থেকে আমার সর্বজনীন ইন্টারফেসে (ওআরএম রেফারেন্সবিহীন যাদের কাছে) বুদবুদ করার জন্য ব্যবহৃত হয়েছিল।
অবজেক্টটাইপ

5
কাজের তুলনায় কেউ এনাম কাস্ট করতে পারেন:Base.A == (Base)Consume.A
ক্রেসিমির

1
(দশমিক) বেস ব্যবহার করুন। এ == (দশমিক) কনসুম.এ। কারণ: এভাবেই বিট পতাকা / মিশ্রন কাজ মাস্ক (Enum.IsDefined উদাহরণ যেমন হয় msdn.microsoft.com/en-us/library/... )। সুতরাং এনামকে এনামে সংজ্ঞায়িত না করে একটি পূর্ণসংখ্যায় সেট করা যেতে পারে। পরীক্ষা গ্রহণ করুন = 123456;
তমুসজেরোয়েস

3
@ টিমাসজেআরয়েস দশমিক? intআরও অনেক কিছু জানাতে চাই। যখন কোনও এনামের একটি ভগ্নাংশের অংশ থাকে!?!?!
এরিক

কমপক্ষে, এটি নিশ্চিত করে যে সংশ্লিষ্ট এনাম ধ্রুবকের একই সংখ্যার মান রয়েছে। সর্বোপরি, এনামগুলি কেবল পূর্ণসংখ্যার ধ্রুবকের একটি সেট। সি # কার্যকর করে না যে নির্ধারিত মানগুলি ভয়েলড এনাম কনস্ট্যান্ট, অর্থাৎ এনামগুলি কঠোর অর্থে নিরাপদ টাইপ হয় না।
অলিভিয়ার জ্যাকট-ডেসকোম্বেস 16

98

ইন্ট কনস্ট্যান্ট সহ ক্লাস ব্যবহারের উপরের সমাধানগুলিতে টাইপ-নিরাপত্তার অভাব রয়েছে। অর্থাৎ আপনি ক্লাসে সংজ্ঞায়িত নয় এমন নতুন মান আবিষ্কার করতে পারেন। তদ্ব্যতীত উদাহরণ হিসাবে উদাহরণস্বরূপ এই ক্লাসগুলির একটিকে ইনপুট হিসাবে গ্রহণ করে কোনও পদ্ধতি লেখা সম্ভব নয়।

আপনার লিখতে হবে

public void DoSomethingMeaningFull(int consumeValue) ...

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

public class MyBaseEnum
{
    public static readonly MyBaseEnum A = new MyBaseEnum( 1 );
    public static readonly MyBaseEnum B = new MyBaseEnum( 2 );
    public static readonly MyBaseEnum C = new MyBaseEnum( 3 );

    public int InternalValue { get; protected set; }

    protected MyBaseEnum( int internalValue )
    {
        this.InternalValue = internalValue;
    }
}

public class MyEnum : MyBaseEnum
{
    public static readonly MyEnum D = new MyEnum( 4 );
    public static readonly MyEnum E = new MyEnum( 5 );

    protected MyEnum( int internalValue ) : base( internalValue )
    {
        // Nothing
    }
}

[TestMethod]
public void EnumTest()
{
    this.DoSomethingMeaningful( MyEnum.A );
}

private void DoSomethingMeaningful( MyBaseEnum enumValue )
{
    // ...
    if( enumValue == MyEnum.A ) { /* ... */ }
    else if (enumValue == MyEnum.B) { /* ... */ }
    // ...
}

7
আমি মনে করি এটি সঠিক উত্তর। এনামের জন্য আপনার উত্তরাধিকার থাকতে পারে না তবে এটি আপনাকে এটি পরিচালনা করতে দেয়!
রোবব

11
সুন্দর এবং পরিষ্কার। +1 টি। কেবল একটি ইঙ্গিত, আপনার সত্যিকার অর্থে কোন মান প্রয়োজন হয় না don't
ইগনাসিও সোলার গার্সিয়া

1
আমি কখনই গণনা নিয়ে ভাবি নি যে আপনি ফাইলওপেনমোড বলতে পারেন R পড়ুন> ফাইলঅপেনমোড.ওরাইট। যদি তা কেস হয় তবে সেই এনামের জন্য আপনার একটি ইন্টিউল বা আরও ভাল একটি আইক্যুয়্যালিটি কম্পিউটার দরকার need শুভেচ্ছা।
Ignacio সৌর গার্সিয়া

3
@ বিঙ্কি এলোমেলোভাবে ব্যবহার করে সমাবেশের objectপ্রতিটি ইনস্ট্যান্টেশনের জন্য মানগুলি আলাদা করে তুলবে যাতে সেগুলি সিরিয়াল করা যায় না।
ivan_pozdeev

2
তবে এটি আপনাকে মাইএনমে "স্যুইচ" করতে দেয় না, তাই না? আমার অর্থ
হ'ল

13

বেসটি একটি সংরক্ষিত শব্দ এটি উপেক্ষা করে আপনি এনামের উত্তরাধিকার করতে পারবেন না।

আপনি যা করতে পারেন তা সর্বোত্তম জিনিস হ'ল:

public enum Baseenum
{
   x, y, z
}

public enum Consume
{
   x = Baseenum.x,
   y = Baseenum.y,
   z = Baseenum.z
}

public void Test()
{
   Baseenum a = Baseenum.x;
   Consume newA = (Consume) a;

   if ((Int32) a == (Int32) newA)
   {
   MessageBox.Show(newA.ToString());
   }
}

যেহেতু এগুলি সমস্ত একই বেস টাইপ (যেমন: int) আপনি এক ধরণের উদাহরণ থেকে অন্যটি যে কোনও কাস্টের জন্য মূল্য নির্ধারণ করতে পারেন। আদর্শ নয় তবে এটি কাজ করে।


2
বেসটি সংরক্ষিত তবে বেজটি নেই
এরিক্কল্লান

2
তিনি এনএম নাম হিসাবে অপের বেসের ব্যবহারের কথা উল্লেখ করছেন, এটি ঠিক একটি উদাহরণের নাম আমি নিশ্চিত
জন রস রাশ

জেনিসিওর উত্তর হিসাবে একই।
নওফাল

6

আমি জানি এই উত্তরটি দেরিতে হলেও এটাই আমি শেষ করেছিলাম:

public class BaseAnimal : IEquatable<BaseAnimal>
{
    public string Name { private set; get; }
    public int Value { private set; get; }

    public BaseAnimal(int value, String name)
    {
        this.Name = name;
        this.Value = value;
    }

    public override String ToString()
    {
        return Name;
    }

    public bool Equals(BaseAnimal other)
    {
        return other.Name == this.Name && other.Value == this.Value;
    }
}

public class AnimalType : BaseAnimal
{
    public static readonly BaseAnimal Invertebrate = new BaseAnimal(1, "Invertebrate");

    public static readonly BaseAnimal Amphibians = new BaseAnimal(2, "Amphibians");

    // etc        
}

public class DogType : AnimalType
{
    public static readonly BaseAnimal Golden_Retriever = new BaseAnimal(3, "Golden_Retriever");

    public static readonly BaseAnimal Great_Dane = new BaseAnimal(4, "Great_Dane");

    // etc        
}

তারপরে আমি এই জাতীয় জিনিসগুলি করতে সক্ষম:

public void SomeMethod()
{
    var a = AnimalType.Amphibians;
    var b = AnimalType.Amphibians;

    if (a == b)
    {
        // should be equal
    }

    // call method as
    Foo(a);

    // using ifs
    if (a == AnimalType.Amphibians)
    {
    }
    else if (a == AnimalType.Invertebrate)
    {
    }
    else if (a == DogType.Golden_Retriever)
    {
    }
    // etc          
}

public void Foo(BaseAnimal typeOfAnimal)
{
}

2
ম্যাজিক নম্বরগুলি স্ট্যাকওভারফ্লো / প্রশ্নগুলি / 757684/ … অনুযায়ী অবজেক্টের সাথে প্রতিস্থাপন করা যেতে পারে । তবে এই বিশেষ ক্ষেত্রে, বিদ্যমান জৈবিক নামকরণের বৈশিষ্ট্যগুলি স্বতন্ত্রতার গ্যারান্টি ব্যবহার করে আপনি উভয় বিশ্বের সেরাটি পেতে পারেন।
ivan_pozdeev

4

এটাই আমি করেছি। আমি ভিন্নভাবে যা করেছি তা হ'ল new"গ্রাসকারী" তে একই নাম এবং কীওয়ার্ডটি ব্যবহার করা enum। যেহেতু এর নাম enumএকই, আপনি কেবল নির্বোধভাবে এটি ব্যবহার করতে পারেন এবং এটি সঠিক হবে। এছাড়াও আপনি বুদ্ধি পাবেন। মানটি বেস থেকে অনুলিপি করা হয়েছে এবং সেগুলি সিঙ্ক করে রাখা হয়েছে এমনটি সেট আপ করার সময় আপনাকে কেবল ম্যানুয়ালি যত্ন নিতে হবে। কোড মন্তব্যের পাশাপাশি আপনি এটি সহায়তা করতে পারেন। এটি ডাটাবেসের মধ্যে অন্য কারণগুলির জন্য যখন enumমানগুলি সঞ্চয় করি আমি সর্বদা স্ট্রিংটি সঞ্চয় করি, মানটি না। কারণ আপনি যদি স্বয়ংক্রিয়ভাবে নির্ধারিত ক্রমবর্ধমান পূর্ণসংখ্যার মানগুলি ব্যবহার করেন তবে সেগুলি সময়ের সাথে সাথে পরিবর্তিত হতে পারে।

// Base Class for balls 
public class BaseBall
{
    // keep synced with subclasses!
    public enum Sizes
    {
        Small,
        Medium,
        Large
    }
}

public class VolleyBall : BaseBall
{
    // keep synced with base class!
    public new enum Sizes
    {
        Small = BaseBall.Sizes.Small,
        Medium = BaseBall.Sizes.Medium,
        Large = BaseBall.Sizes.Large,
        SmallMedium,
        MediumLarge,
        Ginormous
    }
}

2
উদ্ভূত শ্রেণিতে (যেমন SmallMedium = 100,) নতুন মানগুলির জন্য একটি পৃথক পরিসর নির্ধারণের কথা বিবেচনা করুন , সুতরাং আপনি যখন বেস শ্রেণিতে নতুন মান যুক্ত করেন তখন আপনি আপনার সফ্টওয়্যারটির পুরানো সংস্করণগুলির সাথে সামঞ্জস্য রাখতে পারেন। উদাহরণস্বরূপ, Hugeআপনার বেস এনুমে একটি আকার যুক্ত 4করা তার মানকে বরাদ্দ করবে , তবে 4ইতিমধ্যে SmallMediumউদ্ভূত শ্রেণিতে নেওয়া হয়েছে ।
রবার্তো

1
@ রবার্তো, এটির সমাধানের জন্য আমি কখনই এনাম মানগুলি টিকিয়ে রাখি না, কেবল নামগুলি। এবং এগুলি সিঙ্ক করে রাখা এখানে প্রয়োজনীয় requirement তাই Hugeবেস ক্লাসে যোগ করার Hugeআগে সাবক্লাসে একটি দরকার হবেSmallMedium
টুডমো

2
BaseBallএখানে স্মার্টতম নাম নাও হতে পারে। এটা বিভ্রান্তিকর. যেহেতু একটি বেসবল আসলে একটি জিনিস। আপনি যদি মিস করেন যে এটি বলের জন্য কেবল একটি বেস ক্লাস, এটি খুব অদ্ভুত দেখাচ্ছে যে কোনও ভলিবল শারীরিকভাবে ছোট বেসবল থেকে উত্তরাধিকার সূত্রে :) :) আমার পরামর্শটি কেবলমাত্র ব্যবহার করতে হবেBall
নিক এন।

3

বিকল্প সমাধান

আমার সংস্থায়, আমরা অ-সাধারণ নিম্ন স্তরের প্রকল্পগুলি পেতে "প্রকল্পের উপরের ঝাঁপ" এড়াতে পারি। উদাহরণস্বরূপ, আমাদের উপস্থাপনা / এপিআই স্তরটি কেবলমাত্র আমাদের ডোমেন স্তরকেই রেফারেন্স করতে পারে এবং ডোমেন স্তরটি কেবল ডেটা স্তরকেই রেফারেন্স করতে পারে।

যাইহোক, যদি এমন এনাম থাকে যা উপস্থাপনা এবং ডোমেন স্তর উভয় দ্বারা রেফারেন্স করা প্রয়োজন তখন এটি একটি সমস্যা।

এখানে আমরা কার্যকরভাবে সমাধান করেছি (এখনও অবধি) সমাধান। এটি একটি দুর্দান্ত সমাধান এবং আমাদের জন্য ভাল কাজ করে। অন্যান্য উত্তরগুলি এই চারদিকে হিট করছে।

প্রাথমিক ভিত্তি হ'ল enums উত্তরাধিকারসূত্রে প্রাপ্ত হতে পারে না - তবে ক্লাসগুলি পারে। তাই ...

// In the lower level project (or DLL)...
public abstract class BaseEnums
{
    public enum ImportanceType
    {
        None = 0,
        Success = 1,
        Warning = 2,
        Information = 3,
        Exclamation = 4
    }

    [Flags]
    public enum StatusType : Int32
    {
        None = 0,
        Pending = 1,
        Approved = 2,
        Canceled = 4,
        Accepted = (8 | Approved),
        Rejected = 16,
        Shipped = (32 | Accepted),
        Reconciled = (64 | Shipped)
    }

    public enum Conveyance
    {
        None = 0,
        Feet = 1,
        Automobile = 2,
        Bicycle = 3,
        Motorcycle = 4,
        TukTuk = 5,
        Horse = 6,
        Yak = 7,
        Segue = 8
    }

তারপরে, আরও একটি উচ্চ স্তরের প্রকল্পের এনামগুলিকে "উত্তরাধিকারী" করতে ...

// Class in another project
public sealed class SubEnums: BaseEnums
{
   private SubEnums()
   {}
}

এর তিনটি বাস্তব সুবিধা রয়েছে ...

  1. উভয় প্রকল্পে এনাম সংজ্ঞাগুলি স্বয়ংক্রিয়ভাবে একই - সংজ্ঞা অনুসারে।
  2. এনাম সংজ্ঞাগুলির যে কোনও পরিবর্তনগুলি দ্বিতীয় শ্রেণিতে কোনও পরিবর্তন না করে স্বয়ংক্রিয়ভাবে দ্বিতীয়টিতে প্রতিধ্বনিত হয়।
  3. এনামগুলি একই কোডের উপর ভিত্তি করে - যাতে মানগুলি সহজেই তুলনা করা যায় (কিছু ক্যাভ্যাট সহ)।

প্রথম প্রকল্পের এনামগুলিকে উল্লেখ করতে , আপনি শ্রেণীর উপসর্গটি ব্যবহার করতে পারেন: বেসেনমস.স্ট্যাটাসটাইপ.পেন্ডিং বা যুক্ত করুন "স্ট্যাটিক বেসেনম ব্যবহার করে";আপনার ব্যবহারের বিবৃতি।

ইন দ্বিতীয় প্রকল্পের যখন তবে উত্তরাধিকারসূত্রে বর্গ সঙ্গে তার আচরণ, আমি পাই নি "স্ট্যাটিক ব্যবহার ..." কাজ পদ্ধতির, তাই "উত্তরাধিকারসূত্রে enums" এ সমস্ত রেফারেন্স বর্গ সঙ্গে পূর্বে সমাধান করা হবে, যেমন SubEnums.StatusType.Pending । যদি কেউ "স্ট্যাটিক ব্যবহার করে " অনুমতি দেওয়ার উপায় নিয়ে আসে দ্বিতীয় প্রকল্পে পদ্ধতির তবে আমাকে জানান।

আমি নিশ্চিত যে এটি আরও উন্নত করার জন্য এটি টুইট করা যেতে পারে - তবে এটি আসলে কাজ করে এবং আমি কার্যপ্রণালীতে এই পদ্ধতির ব্যবহার করেছি।

আপনি যদি সহায়ক মনে করেন তবে এটির জন্য ভোট দিন।


2

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

  • অন্তর্নিহিত ইন্টার মানের স্বয়ংক্রিয় বর্ধন
  • স্বয়ংক্রিয় নামকরণ

এটি একটি বাক্সের বাইরে সমাধান এবং আপনার প্রকল্পে সরাসরি beোকানো যেতে পারে। এটি আমার প্রয়োজন হিসাবে ডিজাইন করা হয়েছে, সুতরাং আপনি যদি এর কিছু অংশ পছন্দ না করেন তবে কেবল নিজের কোড দিয়ে সেগুলি প্রতিস্থাপন করুন।

প্রথমত, বেস CEnumকাস্টমটি রয়েছে যা সমস্ত কাস্টম এনামদের উত্তরাধিকার সূত্রে প্রাপ্ত হতে হবে। এটি নেট কার্যকারিতার মতো বুনিয়াদি কার্যকারিতা রয়েছে Enum:

public class CEnum
{
  protected static readonly int msc_iUpdateNames  = int.MinValue;
  protected static int          ms_iAutoValue     = -1;
  protected static List<int>    ms_listiValue     = new List<int>();

  public int Value
  {
    get;
    protected set;
  }

  public string Name
  {
    get;
    protected set;
  }

  protected CEnum ()
  {
    CommonConstructor (-1);
  }

  protected CEnum (int i_iValue)
  {
    CommonConstructor (i_iValue);
  }

  public static string[] GetNames (IList<CEnum> i_listoValue)
  {
    if (i_listoValue == null)
      return null;
    string[] asName = new string[i_listoValue.Count];
    for (int ixCnt = 0; ixCnt < asName.Length; ixCnt++)
      asName[ixCnt] = i_listoValue[ixCnt]?.Name;
    return asName;
  }

  public static CEnum[] GetValues ()
  {
    return new CEnum[0];
  }

  protected virtual void CommonConstructor (int i_iValue)
  {
    if (i_iValue == msc_iUpdateNames)
    {
      UpdateNames (this.GetType ());
      return;
    }
    else if (i_iValue > ms_iAutoValue)
      ms_iAutoValue = i_iValue;
    else
      i_iValue = ++ms_iAutoValue;

    if (ms_listiValue.Contains (i_iValue))
      throw new ArgumentException ("duplicate value " + i_iValue.ToString ());
    Value = i_iValue;
    ms_listiValue.Add (i_iValue);
  }

  private static void UpdateNames (Type i_oType)
  {
    if (i_oType == null)
      return;
    FieldInfo[] aoFieldInfo = i_oType.GetFields (BindingFlags.Public | BindingFlags.Static);

    foreach (FieldInfo oFieldInfo in aoFieldInfo)
    {
      CEnum oEnumResult = oFieldInfo.GetValue (null) as CEnum;
      if (oEnumResult == null)
        continue;
      oEnumResult.Name = oFieldInfo.Name;
    }
  }
}

দ্বিতীয়ত, এখানে 2 উত্পন্ন এনাম ক্লাস রয়েছে। প্রত্যাশিতভাবে কাজ করার জন্য সমস্ত উত্সযুক্ত শ্রেণীর কিছু প্রাথমিক পদ্ধতি প্রয়োজন। এটি সর্বদা একই বয়লারপ্লেট কোড; বেস ক্লাসে এটি আউটসোর্স করার কোনও উপায় আমি এখনও খুঁজে পাইনি। উত্তরাধিকারের প্রথম স্তরের কোড পরবর্তী সমস্ত স্তর থেকে কিছুটা পৃথক।

public class CEnumResult : CEnum
{
  private   static List<CEnumResult>  ms_listoValue = new List<CEnumResult>();

  public    static readonly CEnumResult Nothing         = new CEnumResult (  0);
  public    static readonly CEnumResult SUCCESS         = new CEnumResult (  1);
  public    static readonly CEnumResult UserAbort       = new CEnumResult ( 11);
  public    static readonly CEnumResult InProgress      = new CEnumResult (101);
  public    static readonly CEnumResult Pausing         = new CEnumResult (201);
  private   static readonly CEnumResult Dummy           = new CEnumResult (msc_iUpdateNames);

  protected CEnumResult () : base ()
  {
  }

  protected CEnumResult (int i_iValue) : base (i_iValue)
  {
  }

  protected override void CommonConstructor (int i_iValue)
  {
    base.CommonConstructor (i_iValue);

    if (i_iValue == msc_iUpdateNames)
      return;
    if (this.GetType () == System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType)
      ms_listoValue.Add (this);
  }

  public static new CEnumResult[] GetValues ()
  {
    List<CEnumResult> listoValue = new List<CEnumResult> ();
    listoValue.AddRange (ms_listoValue);
    return listoValue.ToArray ();
  }
}

public class CEnumResultClassCommon : CEnumResult
{
  private   static List<CEnumResultClassCommon> ms_listoValue = new List<CEnumResultClassCommon>();

  public    static readonly CEnumResult Error_InternalProgramming           = new CEnumResultClassCommon (1000);

  public    static readonly CEnumResult Error_Initialization                = new CEnumResultClassCommon ();
  public    static readonly CEnumResult Error_ObjectNotInitialized          = new CEnumResultClassCommon ();
  public    static readonly CEnumResult Error_DLLMissing                    = new CEnumResultClassCommon ();
  // ... many more
  private   static readonly CEnumResult Dummy                               = new CEnumResultClassCommon (msc_iUpdateNames);

  protected CEnumResultClassCommon () : base ()
  {
  }

  protected CEnumResultClassCommon (int i_iValue) : base (i_iValue)
  {
  }

  protected override void CommonConstructor (int i_iValue)
  {
    base.CommonConstructor (i_iValue);

    if (i_iValue == msc_iUpdateNames)
      return;
    if (this.GetType () == System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType)
      ms_listoValue.Add (this);
  }

  public static new CEnumResult[] GetValues ()
  {
    List<CEnumResult> listoValue = new List<CEnumResult> (CEnumResult.GetValues ());
    listoValue.AddRange (ms_listoValue);
    return listoValue.ToArray ();
  }
}

ক্লাসগুলি ফোলউইং কোড সহ সফলভাবে পরীক্ষা করা হয়েছে:

private static void Main (string[] args)
{
  CEnumResult oEnumResult = CEnumResultClassCommon.Error_Initialization;
  string sName = oEnumResult.Name;   // sName = "Error_Initialization"

  CEnum[] aoEnumResult = CEnumResultClassCommon.GetValues ();   // aoEnumResult = {testCEnumResult.Program.CEnumResult[9]}
  string[] asEnumNames = CEnum.GetNames (aoEnumResult);
  int ixValue = Array.IndexOf (aoEnumResult, oEnumResult);    // ixValue = 6
}

1

এনামগুলি এগুলির মতো দেখা হলেও প্রকৃত ক্লাস নয়। অভ্যন্তরীণভাবে, তারা কেবল তাদের অন্তর্নিহিত ধরণের (পূর্বনির্ধারিত Int32 দ্বারা) চিকিত্সা করা হয়। অতএব, আপনি কেবল এটি করতে পারেন একটি এনাম থেকে অন্য এনামে একক মানগুলি "অনুলিপি" করে এবং সমতার জন্য তাদের তুলনা করার জন্য তাদের পূর্ণসংখ্যার সাথে কাস্ট করে।


1

এনামগুলি অন্যান্য এনাম থেকে প্রাপ্ত করা যায় না তবে কেবল ইনট, ইউিন্ট, শর্ট, ইউশোর্ট, লং, উলং, বাইট এবং এসবিট থেকে নেওয়া হয়।

পাস্কাল বলেছিলেন, আপনি এনাম মান শুরু করার জন্য অন্যান্য এনামের মান বা ধ্রুবক ব্যবহার করতে পারেন তবে এটি প্রায়।


8
এটি সি # সিনট্যাক্সের কারণে কিছুটা মিসনোমার হলেও এটি এনটস আসলে ইনট, ইউন্ট ইত্যাদি থেকে উত্তরাধিকারী হতে পারে না ... হুডের নীচে তারা এখনও সিস্টেম.ইনুমের উত্তরাধিকারী। এটা ঠিক যে এনামের প্রতিনিধিত্বকারী সদস্যটি int, uint ইত্যাদি টাইপ করা হয় ...
JaredPar

@JaredPar। যখন কোনও এনাম একটি ইউন্ট থেকে উদ্ভূত হয়, তার অর্থ এটির মানগুলি সমস্ত মেশিন ইত্যাদি default ডিফল্টরূপে একটি এনাম উত্তরাধিকার সূত্রে প্রাপ্ত হয়। (সি # স্পেসিফিকেশনটি একবার দেখুন, এনাম সুম ইনম: ইউন্ট {...} আসলে কাজ করে))
জেরোইন ল্যান্ডহির

4
আসলে না. এটি System.enum এর উত্তরাধিকার সূত্রে প্রাপ্ত। যেমন আগে এবং আরও প্রায়ই এখানে পোস্ট করা হয়েছিল, আপনি যা উত্তরাধিকার বলে মনে করেন তা হ'ল csharp এ কেবলমাত্র একটি ল্যাঙ্গেজ দুসাম্বিগুইটি।
টমটম

1

আর একটি সম্ভাব্য সমাধান:

public enum @base
{
    x,
    y,
    z
}

public enum consume
{
    x = @base.x,
    y = @base.y,
    z = @base.z,

    a,b,c
}

// TODO: Add a unit-test to check that if @base and consume are aligned

আছে HTH


1

এটি সম্ভব নয় (যেমনটি ইতিমধ্যে উল্লিখিত @ জারেডপার)। এটিকে ঘিরে কাজ করার পক্ষে যুক্তি রাখার চেষ্টা করা একটি খারাপ অভ্যাস। যদি আপনি একটি আছে base classআছে একটি enum, আপনি সমস্ত সম্ভব তালিকাবদ্ধ করা উচিতenum-values সেখানে এবং ক্লাস বাস্তবায়ন মান যে তা জানেন সঙ্গে কাজ করা উচিত।

যেমন ধরুন আপনার একটি বেস ক্লাস রয়েছে BaseCatalog, এবং এটির একটি enum ProductFormats( Digital, Physical) রয়েছে। তারপরে আপনার একটি MusicCatalogবা BookCatalogএতে দুটি Digitalএবং Physicalপণ্য উভয়ই থাকতে পারে তবে শ্রেণিটি যদি হয় তবে ClothingCatalogএটিতে কেবল Physicalপণ্য থাকতে হবে।


1

আমি বুঝতে পারি যে আমি এই পার্টিতে কিছুটা দেরি করেছি, তবে এখানে আমার দুটি সেন্ট রয়েছে।

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

পরিচিতি: অবজেক্টইনম

আপনি এখানে কোড এবং ডকুমেন্টেশন চেক করতে পারেন: https://github.com/dimi3tron/ObjectEnum

এবং প্যাকেজ এখানে: https://www.nuget.org/packages/ObjectEnum

অথবা কেবল এটি ইনস্টল করুন: Install-Package ObjectEnum

সংক্ষেপে, ObjectEnum<TEnum> কোনও এনামের জন্য মোড়কের কাজ করে। সাবক্লাসে গেটডিফাইনডভ্যালুগুলি () ওভাররাইড করে যে কেউ এই নির্দিষ্ট শ্রেণীর জন্য কোন এনাম মানগুলি কার্যকর তা নির্দিষ্ট করতে পারে।

একটি তৈরি করতে বেশ কয়েকটি অপারেটর ওভারলোডগুলি যুক্ত করা হয়েছে ObjectEnum<TEnum>সংজ্ঞায়িত মান সীমাবদ্ধতার কথা মাথায় রেখে অন্তর্নিহিত এনামের উদাহরণ হিসাবে আচরণ । এর অর্থ আপনি সহজেই কোনও প্রাক বা এনাম মানের সাথে উদাহরণটি তুলনা করতে পারেন এবং এইভাবে এটি একটি স্যুইচ কেস বা অন্য কোনও শর্তাধীন ব্যবহার করতে পারেন।

আমি উদাহরণ এবং আরও তথ্যের জন্য উপরের গিথুব রেপো উল্লেখ করতে চাই।

আশা করি এটি আপনার কাজে লাগবে। আরও চিন্তাভাবনা বা মতামতের জন্য গিথুবকে দ্বিধা প্রকাশ করতে বা মন্তব্য করতে দ্বিধা বোধ করবেন।

আপনি যা করতে পারেন তার কয়েকটি সংক্ষিপ্ত উদাহরণ এখানে দেওয়া হল ObjectEnum<TEnum>:

var sunday = new WorkDay(DayOfWeek.Sunday); //throws exception
var monday = new WorkDay(DayOfWeek.Monday); //works fine
var label = $"{monday} is day {(int)monday}." //produces: "Monday is day 1."
var mondayIsAlwaysMonday = monday == DayOfWeek.Monday; //true, sorry...

var friday = new WorkDay(DayOfWeek.Friday);

switch((DayOfWeek)friday){
    case DayOfWeek.Monday:
        //do something monday related
        break;
        /*...*/
    case DayOfWeek.Friday:
        //do something friday related
        break;
}

-8

আপনি এনামে উত্তরাধিকার সম্পাদন করতে পারেন, তবে এটি কেবলমাত্র নিম্নলিখিত ধরণের মধ্যে সীমাবদ্ধ। int, uint, বাইট, sbyte, সংক্ষিপ্ত, ushort, দীর্ঘ, উলং

যেমন

public enum Car:int{
Toyota,
Benz,
}

2
আমি মনে করি ওপি শুধু একটি বেস সাংখ্যিক ধরণ থেকে পরস্পর এক enum উত্তরাধিকারী, জিজ্ঞাসা ছিল (যা সব enums C # এর না, হয় পরোক্ষভাবে বা স্পষ্টভাবে।)
reirab
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.