열거 형“상속”


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그 모두 포함 할 수 DigitalPhysical제품을, 그러나 클래스 인 경우 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.