열거 형“상속”


391

저수준 네임 스페이스에 열거 형이 있습니다. 저수준 열거 형을 "상속"하는 중간 수준 네임 스페이스에 클래스 또는 열거 형을 제공하고 싶습니다.

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

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

나는 이것이 가능하거나 열거 형 소비를 대체 할 수있는 일종의 클래스가 있기를 바라고 있습니다.

생각?

편집 : 클래스에서 const로 전환하지 않은 이유 중 하나는 내가 사용해야하는 서비스에 저수준 열거가 필요하기 때문입니다. 구조를 열거 형으로 정의하는 WSDL과 XSD를 받았습니다. 서비스를 변경할 수 없습니다.


답변:


462

이건 불가능 해. 열거 형은 다른 열거 형에서 상속 할 수 없습니다. 실제로 모든 열거 형은 실제로에서 상속해야합니다 System.Enum. C #에서는 구문이 상속처럼 보이는 열거 형 값의 기본 표현을 변경할 수 있지만 실제로는 System.enum에서 상속됩니다.

자세한 내용은 CLI 사양 8.5.2 단원을 참조 하십시오. 사양의 관련 정보

  • 모든 열거 형은 System.Enum
  • 위의 때문에 모든 열거 형은 값 유형이므로 봉인됩니다.

2
그리고 모든 가치 유형은 System.ValueType에서 파생됩니다
— Raz Megrelidze

4
@Seven의 답변은 합법적 인 해결책입니다 : stackoverflow.com/a/4042826/538387
— Tohid

그러나 @Steven의 답변은 switch상황에 따라 사용할 수 없습니다 .
— zionpi

@zionpi 그렇습니다. 그러나 표준 스위치는 그렇지 않으면 블록이있을 경우 전체와 동일한 IL 코드로 컴파일됩니다. 어쨌든 더 나은 구문이 있다고 생각합니다. resharper / VS가 모든 사례 진술을 자동 완성하는 능력을 잃어 버렸지 만 그것이 세상의 끝이 아니라고 생각합니다. 개인적 취향이지만 스위치 설명의 팬이 아닙니다.
— MemeDeveloper

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)
— Mike de Klerk

1
리플렉션을 사용할 수 있습니다 : void Test() { foreach (System.Reflection.PropertyInfo pi in typeof(Consume).GetProperties()) { Console.WriteLine(pi.Name); } }
— mnieto

2
리플렉션을 사용하여 속성을 수집하면 상속 된 Object 속성을 무시해야합니다.
— Robert

그 작업에 대한 반성은 매우 추악합니다.
— dylanh724

1
Reflection을 사용할 필요가 없습니다. codeproject.com/Articles/20805/Enhancing-C-Enums 의 구현 은 객체를 만들 때 목록에 추가되고 해당 목록을 사용할 수있는 좋은 방법입니다. 객체 유형 목록을 반환합니다. 상속과 함께 사용하면 상속 클래스에 올바른 목록을 사용하고 있는지 확인해야합니다.
— PBo

112

짧은 대답은 '아니요'입니다. 원하는 경우 조금만 재생할 수 있습니다.

항상 다음과 같은 작업을 수행 할 수 있습니다.

private enum Base
{
    A,
    B,
    C
}

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

그러나 Base.A! = Consume.A 때문에 그렇게 훌륭하게 작동하지는 않습니다.

그래도 항상 다음과 같은 작업을 수행 할 수 있습니다.

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

Base와 Consume을 교차하려면 ...

열거 형의 값을 정수로 캐스팅하고 열거 형 대신 정수로 비교할 수도 있지만 그러한 종류의 짜증도 있습니다.

확장 메소드 리턴은 유형 T를 캐스트해야합니다.


4
나는 이것을 파 낸다. 이 개념을 사용하여 ORM에서 공용 인터페이스 (ORM 참조가없는 것)에 열거 할 수 있습니다.
— ObjectType

5
작업과 비교하기 위해 열거 형을 캐스팅 할 수 있습니다.Base.A == (Base)Consume.A
— Kresimir

1
(소수) Base.A == (소수) 소비를 사용하십시오. 이유 : 비트 플래그 / 마스크 결합이 작동하는 방식입니다 (예 : Enum.IsDefined msdn.microsoft.com/en-us/library/… ). 따라서 열거 형은 열거 형에 정의되지 않은 정수로 설정할 수 있습니다. 테스트 소비 = 123456;
— TamusJRoyce

3
@TamusJRoyce 10 진수? int훨씬 더 이해가 될 것입니다. 열거 형에 소수 부분이 언제입니까!?!?!
— ErikE

적어도, 이것은 대응하는 열거 형 정수가 동일한 정수 값을 갖도록합니다. 결국 열거 형은 정수 상수의 집합 일뿐입니다. C #에서는 할당 된 값을 사용 가능한 열거 형 상수로 강제하지 않습니다. 즉, 열거 형은 엄격한 의미에서 형식이 안전하지 않습니다.
— Olivier Jacot-Descombes

98

정수 상수가있는 클래스를 사용하는 위의 솔루션에는 형식 안전성이 없습니다. 즉, 클래스에 실제로 정의되지 않은 새로운 값을 발명 할 수 있습니다. 또한 예를 들어 이러한 클래스 중 하나를 입력으로 사용하는 메소드를 작성할 수 없습니다.

당신은 쓸 필요가있을 것입니다

public void DoSomethingMeaningFull(int consumeValue) ...

그러나 사용 가능한 열거 형이 없었던 Java의 클래스 기반 솔루션이 있습니다. 이것은 거의 열거 같은 행동을 제공합니다. 유일한 경고는 이러한 상수를 switch 문 내에서 사용할 수 없다는 것입니다.

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
나는 이것이 정답이라고 생각합니다. Enum에 대한 상속을 가질 수는 없지만이를 통해 관리 할 수 ​​있습니다!
— robob

11
좋고 깨끗합니다. +1. 힌트 만하면 실제로 int 값이 필요하지 않습니다.
— Ignacio Soler Garcia

1
FileOpenMode.Read> FileOpenMode.Write라고 말할 수있는 것처럼 열거 형을 생각하지 않았습니다. 이 경우 해당 열거 형에 대한 int 또는 더 나은 IEqualityComparer가 필요합니다. 문안 인사.
— 이그나시오 솔러 가르시아

3
random을 사용하는 @binki object는 어셈블리의 각 인스턴스화마다 값이 다르므로 직렬화 할 수 없습니다.
— ivan_pozdeev

2
그러나 이것이 MyEnum을 "전환"할 수는 없습니까? 이것이 주로 열거 형을 사용하는 이유입니다.
— MemphiZ

13

base가 예약어라는 사실을 무시하면 enum의 상속을 수행 할 수 없습니다.

가장 좋은 방법은 다음과 같습니다.

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
기본은 예약되어 있지만 기본은 예약되어 있지 않습니다
— erikkallen

2
그는 OP의 기본 이름을 열거 형 이름으로 사용하는 것을 언급하고 있습니다. 이것은 단지 확실한 이름 일뿐입니다
— John Rasch

Genisio의 답변과 동일합니다.
— nawfal

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
매직 숫자는 stackoverflow.com/questions/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.
— Roberto

1
@Roberto, 이것을 해결하기 위해 열거 형 값을 유지하지 않고 이름 만 유지합니다. 동기화 상태를 유지해야합니다. 따라서 Huge기본 클래스에 추가 하려면 Huge이전에 서브 클래스에 a가 필요합니다 .SmallMedium
— toddmo

2
BaseBall여기서 가장 똑똑한 이름이 아닐 수도 있습니다. 그건 헷갈 린다. 야구는 실제로 일이기 때문에. 이것이 볼의 기본 클래스라는 것을 놓치면 배구가 물리적으로 더 작은 야구에서 상속된다는 것은 매우 이상하게 보입니다. :). 내 제안은 그냥 사용하는 것입니다Ball
— Nick N.

3

대체 솔루션

우리 회사에서는 일반적이지 않은 하위 레벨 프로젝트에 도달하기 위해 "프로젝트를 뛰어 넘다"는 것을 피합니다. 예를 들어 프레젠테이션 / API 계층은 도메인 계층 만 참조 할 수 있으며 도메인 계층은 데이터 계층 만 참조 할 수 있습니다.

그러나 이는 프레젠테이션 및 도메인 계층 모두에서 참조해야하는 열거 형이있을 때 문제가됩니다.

여기에 지금까지 구현 한 솔루션이 있습니다. 그것은 꽤 좋은 해결책이며 우리에게 잘 작동합니다. 다른 대답은이 주위에 치고 있었다.

기본 전제는 열거 형을 상속 할 수 없지만 클래스는 상속 할 수 없다는 것입니다. 그래서...

// 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. 열거 형은 동일한 코드를 기반으로하므로 값을 쉽게 비교할 수 있습니다 (몇 가지주의 사항이 있음).

첫 번째 프로젝트 에서 열거 형을 참조하려면 클래스의 접두사를 사용하십시오. BaseEnums.StatusType.Pending 또는 "정적 BaseEnums 사용"; 당신의 사용에 진술.

에서 두 번째 프로젝트 그러나 상속 클래스를 처리, I는 얻을 수 없었다 "정적을 사용하여 ..." 은 "상속 열거 형"에 대한 모든 참조가 클래스로 시작 될 수 있도록 작업에 대한 접근 방식을, 예를 들어 SubEnums.StatusType.Pending . 사람이 할 수있는 방법과 함께 오면 "을 사용하여 정적" 접근 방식은 두 번째 프로젝트에 사용되는, 알려주세요.

나는 이것이 더 나아질 수 있도록 조정할 수 있다고 확신하지만 실제로 작동하며 작업중 인 프로젝트 에서이 접근법을 사용했습니다.

도움이 될 경우 투표하십시오.


2

나는 또한 Enum을 과부하시키고 싶었고이 페이지의 'Seven' 과 'Merlyn Morgan-Graham'의 대답을 중복 된 게시물 과 함께 몇 가지 개선 사항을 혼합하여 만들었습니다 .
다른 솔루션보다 내 솔루션의 주요 장점 :

  • 기본 int 값의 자동 증분
  • 자동 명명

이것은 즉시 사용 가능한 솔루션이며 프로젝트에 직접 삽입 될 수 있습니다. 그것은 내 요구에 맞게 설계되었으므로 일부를 좋아하지 않으면 자신의 코드로 바꾸십시오.

먼저 CEnum모든 사용자 지정 열거 형에서 상속해야하는 기본 클래스 가 있습니다. .net 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 개의 파생 Enum 클래스가 있습니다. 모든 파생 클래스는 예상대로 작동하려면 몇 가지 기본 방법이 필요합니다. 항상 같은 상용구 코드입니다. 아직 기본 클래스에 아웃소싱하는 방법을 찾지 못했습니다. 상속의 첫 번째 수준의 코드는 모든 후속 수준과 약간 다릅니다.

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

열거 형은 다른 열거 형에서 파생 될 수 없지만 int, uint, short, ushort, long, ulong, byte 및 sbyte에서만 파생됩니다.

Pascal이 말했듯이 다른 열거 형 값이나 상수를 사용하여 열거 형 값을 초기화 할 수 있지만 그 정도입니다.


8
C # 구문 때문에 약간의 오해이지만 enum은 실제로 int, uint 등으로부터 상속받을 수 없습니다 ... 후드 아래에서 여전히 System.Enum에서 상속합니다. 열거 형을 나타내는 멤버가 int, uint 등으로 입력되는 것입니다.
— JaredPar

@JaredPar. 열거 형이 uint에서 파생되면 값이 모두 uint 등임을 의미합니다. 기본적으로 열거 형은 int를 상속합니다. (C # 사양 enum SomeEnum : uint {...}이 실제로 작동 함)을
— 살펴보십시오

4
사실은 아니야 System.enum을 상속합니다. 이전에 그리고 더 자주 여기에 게시 된 것처럼 상속이라고 생각하는 것은 csharp의 단순한 허풍입니다.
— TomTom

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

@JaredPar가 이미 언급했듯이 이것은 불가능합니다. 이 문제를 해결하기 위해 논리를 적용하는 것은 나쁜 습관입니다. 경우에 당신은이 base class이 즉 enum, 모든 수의 나열해야 enum-values이, 그리고 클래스의 구현은 알고있는 값으로 작동합니다.

예 : 당신이 기본 클래스를 세웠 BaseCatalog하고는있다 enum ProductFormats( Digital, Physical). 그런 다음 당신은있을 수 있습니다 MusicCatalog또는 BookCatalog그 모두 포함 할 수 Digital및 Physical제품을, 그러나 클래스 인 경우 ClothingCatalog,이있는 경우에만한다 Physical제품.


1

나는이 파티에 조금 늦었다는 것을 알고 있지만 여기에 2 센트가 있습니다.

우리는 프레임 워크가 Enum 상속을 지원하지 않는다는 것을 분명히 알고 있습니다. 이 스레드에서 매우 흥미로운 해결 방법이 제안되었지만 그 중 어느 것도 내가 찾고있는 것 같은 느낌이 들지 않았으므로 직접 살펴 보았습니다.

소개 : ObjectEnum

https://github.com/dimi3tron/ObjectEnum 에서 코드와 설명서를 확인할 수 있습니다 .

그리고 여기 패키지는 https://www.nuget.org/packages/ObjectEnum

또는 그냥 설치하십시오. Install-Package ObjectEnum

즉, ObjectEnum<TEnum>모든 열거 형의 래퍼 역할을합니다. 서브 클래스에서 GetDefinedValues ​​()를 재정 의하여이 특정 클래스에 유효한 열거 값을 지정할 수 있습니다.

ObjectEnum<TEnum>정의 된 값 제한을 염두에두고 인스턴스가 기본 열거 형의 인스턴스 인 것처럼 동작하도록 여러 연산자 오버로드가 추가되었습니다 . 즉, 인스턴스를 int 또는 enum 값과 쉽게 비교할 수 있으므로 스위치 케이스 또는 기타 조건부에서 사용할 수 있습니다.

예제 및 추가 정보는 위의 github repo 언급을 참조하고 싶습니다.

이 정보가 도움이 되길 바랍니다. 추가 의견이나 의견이 있으시면 언제든지 github에 의견을 보내거나 문제를여십시오.

다음은 할 수있는 몇 가지 간단한 예입니다 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, byte, sbyte, short, ushort, long, ulong

예 :

public enum Car:int{
Toyota,
Benz,
}

2
OP가 기본 숫자 형식 (모든 열거 형이 C #에서 암시 적으로 또는 명시 적으로
— 수행함
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.