C # 및 Java Enum (C #을 처음 사용하는 사용자)


182

나는 한동안 Java로 프로그래밍 해 왔으며 C #으로 작성된 프로젝트에 방금 던져졌습니다. C #에서 속도를 높이려고 노력 중이며 새 프로젝트의 여러 곳에서 열거 형이 사용되는 것을 보았지만 언뜻보기에 C #의 열거 형은 Java 1.5 + 구현보다 단순한 것으로 보입니다. 누구나 C #과 Java 열거 형의 차이점과 차이점을 극복하는 방법을 열거 할 수 있습니까? (언어 화염 전쟁을 시작하고 싶지 않고 Java에서했던 C #에서 몇 가지 작업을 수행하는 방법을 알고 싶습니다.) 예를 들어 누군가 Sun의 유명한 Planet enum 예제에 C #을 게시 할 수 있습니까?

public enum Planet {
  MERCURY (3.303e+23, 2.4397e6),
  VENUS   (4.869e+24, 6.0518e6),
  EARTH   (5.976e+24, 6.37814e6),
  MARS    (6.421e+23, 3.3972e6),
  JUPITER (1.9e+27,   7.1492e7),
  SATURN  (5.688e+26, 6.0268e7),
  URANUS  (8.686e+25, 2.5559e7),
  NEPTUNE (1.024e+26, 2.4746e7),
  PLUTO   (1.27e+22,  1.137e6);

  private final double mass;   // in kilograms
  private final double radius; // in meters
  Planet(double mass, double radius) {
      this.mass = mass;
      this.radius = radius;
  }
  public double mass()   { return mass; }
  public double radius() { return radius; }

  // universal gravitational constant  (m3 kg-1 s-2)
  public static final double G = 6.67300E-11;

  public double surfaceGravity() {
      return G * mass / (radius * radius);
  }
  public double surfaceWeight(double otherMass) {
      return otherMass * surfaceGravity();
  }
}

// Example usage (slight modification of Sun's example):
public static void main(String[] args) {
    Planet pEarth = Planet.EARTH;
    double earthRadius = pEarth.radius(); // Just threw it in to show usage

    // Argument passed in is earth Weight.  Calculate weight on each planet:
    double earthWeight = Double.parseDouble(args[0]);
    double mass = earthWeight/pEarth.surfaceGravity();
    for (Planet p : Planet.values())
       System.out.printf("Your weight on %s is %f%n",
                         p, p.surfaceWeight(mass));
}

// Example output:
$ java Planet 175
Your weight on MERCURY is 66.107583
Your weight on VENUS is 158.374842
[etc ...]

1
@ycomp 나는 그것을 인정할 수 없다. Sun (현재 Oracle)에서 제공됩니다. docs.oracle.com/javase/tutorial/java/javaOO/enum.html
Ogre Psalm33

답변:


210

CLR의 열거는 단순히 상수로 명명됩니다. 기본 유형은 정수 여야합니다. Java에서 열거 형은 형식의 명명 된 인스턴스와 비슷합니다. 이 유형은 상당히 복잡 할 수 있으며 예제에서 볼 수 있듯이 다양한 유형의 여러 필드를 포함합니다.

예제를 C #으로 이식하려면 열거 형을 변경할 수없는 클래스로 변경하고 해당 클래스의 정적 읽기 전용 인스턴스를 노출하면됩니다.

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Planet planetEarth = Planet.MERCURY;

            double earthRadius = pEarth.Radius; // Just threw it in to show usage
            double earthWeight = double.Parse("123");
            double earthMass   = earthWeight / pEarth.SurfaceGravity();

            foreach (Planet p in Planet.Values)
                Console.WriteLine($"Your weight on {p} is {p.SurfaceWeight(mass)}");

            Console.ReadKey();
        }
    }

    public class Planet
    {
        public static readonly Planet MERCURY = new Planet("Mercury", 3.303e+23, 2.4397e6);
        public static readonly Planet VENUS   = new Planet("Venus", 4.869e+24, 6.0518e6);
        public static readonly Planet EARTH   = new Planet("Earth", 5.976e+24, 6.37814e6);
        public static readonly Planet MARS    = new Planet("Mars", 6.421e+23, 3.3972e6);
        public static readonly Planet JUPITER = new Planet("Jupiter", 1.9e+27, 7.1492e7);
        public static readonly Planet SATURN  = new Planet("Saturn", 5.688e+26, 6.0268e7);
        public static readonly Planet URANUS  = new Planet("Uranus", 8.686e+25, 2.5559e7);
        public static readonly Planet NEPTUNE = new Planet("Neptune", 1.024e+26, 2.4746e7);
        public static readonly Planet PLUTO   = new Planet("Pluto", 1.27e+22, 1.137e6);

        public static IEnumerable<Planet> Values
        {
            get
            {
                yield return MERCURY;
                yield return VENUS;
                yield return EARTH;
                yield return MARS;
                yield return JUPITER;
                yield return SATURN;
                yield return URANUS;
                yield return NEPTUNE;
                yield return PLUTO;
            }
        }

        public string Name   { get; private set; }
        public double Mass   { get; private set; }
        public double Radius { get; private set; }

        Planet(string name, double mass, double radius) => 
            (Name, Mass, Radius) = (name, mass, radius);

        // Wniversal gravitational constant  (m3 kg-1 s-2)
        public const double G = 6.67300E-11;
        public double SurfaceGravity()            => G * mass / (radius * radius);
        public double SurfaceWeight(double other) => other * SurfaceGravity();
        public override string ToString()         => name;
    }
}

4
우리가 가난한 사람들이 Java 1.4를 사용하도록 강요 한 것은 이런 종류의 안전한 유형입니다 .Java 5의 열거 형은 아마도 스위치 문에서 사용할 수 있기 때문에 Java 5 +의 가장 좋은 기능 일 것입니다.
MetroidFan2002

9
@Chris : 플래그 열거 형 만 복수로 사용해야합니다. 즉, 멤버가 | 운영자.
Kent Boogaart

5
@Mladen : 그것은 전적으로 상황에 달려 있습니다. 행성의 열거는 제한된 수의 행성에 대한 액세스를 제공하는 게임에 완벽하게 적합 할 수 있습니다. 새로운 행성이 게임에 추가되면 코드 변경이 원하는 것일 수 있습니다.
Kent Boogaart

3
@Richie_W Values ​​속성을 사용하여 열거 형을 반복 할 수 있습니다.
Jonathan

23
와우 ... Java에서보다 C #에서 더 장황하게 구현 된 것을 보는 것은 거의 믿을 수 없다
Sune Rasmussen

218

C #에서는 열거 형에 대한 확장 메서드 를 정의 할 수 있으며 이로 인해 누락 된 기능 중 일부가 보완됩니다.

당신은 정의 할 수 있습니다 Planet열거로도에 해당 확장 방법을 가지고 surfaceGravity()surfaceWeight().

Mikhail이 제안한 사용자 정의 속성을 사용 했지만 Dictionary를 사용하여 동일한 속성을 얻을 수 있습니다.

using System;
using System.Reflection;

class PlanetAttr: Attribute
{
    internal PlanetAttr(double mass, double radius)
    {
        this.Mass = mass;
        this.Radius = radius;
    }
    public double Mass { get; private set; }
    public double Radius { get; private set; }
}

public static class Planets
{
    public static double GetSurfaceGravity(this Planet p)
    {
        PlanetAttr attr = GetAttr(p);
        return G * attr.Mass / (attr.Radius * attr.Radius);
    }

    public static double GetSurfaceWeight(this Planet p, double otherMass)
    {
        return otherMass * p.GetSurfaceGravity();
    }

    public const double G = 6.67300E-11;

    private static PlanetAttr GetAttr(Planet p)
    {
        return (PlanetAttr)Attribute.GetCustomAttribute(ForValue(p), typeof(PlanetAttr));
    }

    private static MemberInfo ForValue(Planet p)
    {
        return typeof(Planet).GetField(Enum.GetName(typeof(Planet), p));
    }

}

public enum Planet
{
    [PlanetAttr(3.303e+23, 2.4397e6)]  MERCURY,
    [PlanetAttr(4.869e+24, 6.0518e6)]  VENUS,
    [PlanetAttr(5.976e+24, 6.37814e6)] EARTH,
    [PlanetAttr(6.421e+23, 3.3972e6)]  MARS,
    [PlanetAttr(1.9e+27,   7.1492e7)]  JUPITER,
    [PlanetAttr(5.688e+26, 6.0268e7)]  SATURN,
    [PlanetAttr(8.686e+25, 2.5559e7)]  URANUS,
    [PlanetAttr(1.024e+26, 2.4746e7)]  NEPTUNE,
    [PlanetAttr(1.27e+22,  1.137e6)]   PLUTO
}

20
나는 이것이 더 투표되어야한다고 생각합니다. Java의 열거 형이 작동하는 방식에 더 가깝습니다. Planet.MERCURY.GetSurfaceGravity ()와 같은 것을 할 수 있습니다 <-Enum의 확장 메소드에 주목하십시오!
thenonhacker

2
분명하게 예입니다. 열거 형의 확장 방법 (일반적으로 확장 방법)은 C #에 크게 추가됩니다.
KeithS

3
@AllonGuralnek 감사합니다. 모든 사람이 메타 데이터에 동의하지는 않습니다. 관련 codereview.stackexchange 질문대한 MattDavey의 의견을 참조하십시오 .
finnw

@finnw : Code Review SE 사이트에 대해 들어 본 적이 없습니다. 감사합니다. 나는이 토론을 계속했습니다 (프로그래머에 대한 질문은 여기에서도 필요합니다).
Allon Guralnek

이것은 훌륭한 솔루션입니다-누구든지 이것의 성능을 테스트 했습니까? 예를 들어 클래스의 속성에 액세스하는 것과 비교하여 속성에 액세스하는 데 걸리는 시간
Simon Meyer

35

C #에서 속성은 열거 형과 함께 사용할 수 있습니다. 자세한 설명과 함께이 프로그래밍 패턴의 좋은 예는 다음과 같습니다 (Codeproject)

public enum Planet
{
   [PlanetAttr(3.303e+23, 2.4397e6)]
   Mercury,
   [PlanetAttr(4.869e+24, 6.0518e6)]
   Venus
} 

편집 : 이 질문은 최근에 다시 요청되었고 Jon Skeet에 의해 답변되었습니다 .C #에서 Java의 열거 형과 동등한 것은 무엇입니까? C #의 개인 내부 클래스-왜 더 자주 사용하지 않습니까?

편집 2 : 이 접근법을 매우 화려한 방식으로 확장 하는 수용 된 답변 을보십시오!


1
좋은! 이것은 약간 어리석은 느낌이지만 다른 방법으로 열거 형에 추가 데이터를 추가하는 데 허용되는 방법입니다. 이 훌륭한 솔루션을 언급하는 데 오랜 시간이 걸린다는 사실에 솔직히 놀랐습니다!
오우거 시편 33

13

Java 열거 형은 실제로 개인 생성자와 메서드 등을 가질 수있는 전체 클래스이며 C # 열거 형은 정수입니다. IMO Java의 구현은 훨씬 우수합니다.

이 페이지는 자바 캠프에서 오는 C #을 배우는 동안 많은 도움이 될 것입니다. (링크는 열거 형의 차이점을 나타냅니다 (다른 것들을 위아래로 스크롤)


1
링크가 C #과 Java의 유사점과 차이점에 대한 흥미롭고 광범위한 개요를 제공하지만 텍스트에는 많은 실수가 있습니다 (예 : Java 보호는 C # 내부와 같지만 내부 보호되어야 함). 그래서 당연히 모든 것을 받아들이지 마십시오 :)
mafu

1
Java 팬이라면 Java 열거 형이 우수하다고 말할 수는 없습니다. C #은 FOO = 0ORM 도구에서 사용하기 쉬운 것과 같은 쉬운 정수 선언을 지원합니다 (오류가 발생하기 쉬운 ordinal()사용법 없음). 추가 C #은 특히 매우 유용한 비트 단위 열거 형을 지원합니다 EntityFramework. Java는 열거 형을 확장하여 정수에도 바인딩 할 수 있도록해야합니다. 그렇다면 그들은 우수 할 것입니다 :)
djmj

4

내가 생각하는 이와 같은 것 :

public class Planets 
{
    public static readonly Planet MERCURY = new Planet(3.303e+23, 2.4397e6);
    public static readonly Planet VENUS = new Planet(4.869e+24, 6.0518e6);
    public static readonly Planet EARTH = new Planet(5.976e+24, 6.37814e6);
    public static readonly Planet MARS = new Planet(6.421e+23, 3.3972e6);
    public static readonly Planet JUPITER = new Planet(1.9e+27,   7.1492e7);
    public static readonly Planet SATURN = new Planet(5.688e+26, 6.0268e7);
    public static readonly Planet URANUS = new Planet(8.686e+25, 2.5559e7);
    public static readonly Planet NEPTUNE = new Planet(1.024e+26, 2.4746e7);
    public static readonly Planet PLUTO = new Planet(1.27e+22,  1.137e6);
}

public class Planet
{
    public double Mass {get;private set;}
    public double Radius {get;private set;}

    Planet(double mass, double radius)
    {
        Mass = mass;
        Radius = radius;
    }

    // universal gravitational constant  (m3 kg-1 s-2)
    private static readonly double G = 6.67300E-11;

    public double SurfaceGravity()
    {
        return G * Mass / (Radius * Radius);
    }

    public double SurfaceWeight(double otherMass)
    {
        return otherMass * SurfaceGravity();
    }
}

또는 Planet위와 같이 상수를 클래스에 결합하십시오.


8
확실하지 않습니다-Planet 생성자는 비공개이어야합니다. 열거 형의 요점 중 하나는 고정 된 값 세트라는 것입니다. 그러면 값이 Planet 클래스에서도 정의됩니다.
Jon Skeet

아직. 1) 열거자가 누락되었습니다 :) 2) 열거는 절대 변경 가능해서는 안됩니다. 마지막으로, 코드는 하나의 단일 클래스를 요구합니다 (개인 생성자를 가질 때 특히)
nawfal

3

Java에서 사용 가능한 사용자 정의 동작을 제공하는 또 다른 흥미로운 아이디어가 있습니다. 나는 다음 Enumeration기본 수업을 생각해 냈습니다 .

public abstract class Enumeration<T>
    where T : Enumeration<T>
{   
    protected static int nextOrdinal = 0;

    protected static readonly Dictionary<int, Enumeration<T>> byOrdinal = new Dictionary<int, Enumeration<T>>();
    protected static readonly Dictionary<string, Enumeration<T>> byName = new Dictionary<string, Enumeration<T>>();

    protected readonly string name;
    protected readonly int ordinal;

    protected Enumeration(string name)
        : this (name, nextOrdinal)
    {
    }

    protected Enumeration(string name, int ordinal)
    {
        this.name = name;
        this.ordinal = ordinal;
        nextOrdinal = ordinal + 1;
        byOrdinal.Add(ordinal, this);
        byName.Add(name, this);
    }

    public override string ToString()
    {
        return name;
    }

    public string Name 
    {
        get { return name; }
    }

    public static explicit operator int(Enumeration<T> obj)
    {
        return obj.ordinal;
    }

    public int Ordinal
    {
        get { return ordinal; }
    }
}

기본적으로 형식 매개 변수가 있으므로 순서 수가 다른 파생 열거에서 올바르게 작동합니다. Jon Skeet의 Operator다른 질문에 대한 그의 답변 (http://stackoverflow.com/questions/1376312/whats-the-equivalent-of-javas-enum-in-c) 의 예는 다음과 같습니다.

public class Operator : Enumeration<Operator>
{
    public static readonly Operator Plus = new Operator("Plus", (x, y) => x + y);
    public static readonly Operator Minus =  new Operator("Minus", (x, y) => x - y);
    public static readonly Operator Times =  new Operator("Times", (x, y) => x * y);
    public static readonly Operator Divide = new Operator("Divide", (x, y) => x / y);

    private readonly Func<int, int, int> op;

    // Prevent other top-level types from instantiating
    private Operator(string name, Func<int, int, int> op)
        :base (name)
    {
        this.op = op;
    }

    public int Execute(int left, int right)
    {
        return op(left, right);
    }
}

이것은 몇 가지 장점을 제공합니다.

  • 서수 지원
  • 변환에 stringint있는 스위치 문이 가능합니다
  • GetType ()은 파생 열거 유형의 각 값에 대해 동일한 결과를 제공합니다.
  • 정적 메소드를 System.Enum동일한 기능을 허용하도록 기본 열거 클래스에 추가 할 수 있습니다.

3

우리는 방금 C #에 대한 열거 확장을 만들었습니다 https://github.com/simonmau/enum_ext

typesafeenum에 대한 구현 일 뿐이지 만 훌륭하게 작동하므로 공유 할 패키지를 만들었습니다.

public sealed class Weekday : TypeSafeNameEnum<Weekday, int>
{
    public static readonly Weekday Monday = new Weekday(1, "--Monday--");
    public static readonly Weekday Tuesday = new Weekday(2, "--Tuesday--");
    public static readonly Weekday Wednesday = new Weekday(3, "--Wednesday--");
    ....

    private Weekday(int id, string name) : base(id, name)
    {
    }
}

2

Java 열거 형은 구문 방식으로 열거를 OO 방식으로 표시합니다. 그것들은 Java에서 Enum 클래스를 확장하는 추상 클래스이며, 각 enum 값은 enum 클래스의 정적 최종 공개 인스턴스 구현과 같습니다. 생성 된 클래스를보고 값이 10 인 열거 형 "Foo"의 경우 "Foo $ 1"에서 "Foo $ 10"클래스가 생성됩니다.

C #을 모르지만 해당 언어의 열거 형이 C 스타일 언어의 전통적인 열거 형과 비슷하다고 추측 할 수 있습니다. 빠른 Google 검색에서 여러 값을 보유 할 수 있음을 알았으므로 비슷한 방식으로 구현되었지만 Java 컴파일러가 허용하는 것보다 훨씬 많은 제한이 있습니다.


3
Java 및 C #의 모든 것이 JVM 또는 CLR 바이트 코드의 구문 설탕과 관련이 있습니까? :) 그냥 말하세요
thenonhacker

2

Java 열거 형을 사용하면 컴파일러에서 생성 한 valueOf 메서드를 사용하여 이름에서 쉽게 형식을 안전하게 변환 할 수 있습니다.

// Java Enum has generics smarts and allows this
Planet p = Planet.valueOf("MERCURY");

C #의 원시 열거 형에 해당하는 것이 더 장황합니다.

// C# enum - bit of hoop jumping required
Planet p = (Planet)Enum.Parse(typeof(Planet), "MERCURY");

그러나 Kent에 의해 sugegsted 경로를 내려 가면 ValueOfenum 클래스에서 메서드를 쉽게 구현할 수 있습니다 .


Java 예제는 컴파일러가 생성 한 합성 메소드를 사용하고 있습니다. 제네릭과는 전혀 관련이 없습니다. Enum에는 generic valueOf 메서드가 있지만 Enum이 아닌 Class의 generics를 사용합니다.
Tom Hawtin-tackline

2

C #의 열거 형은 CLR 내부의 상수이지만 익숙하지는 않습니다. Java로 일부 클래스를 디 컴파일했으며 Enums가 일단 변환되고 싶다고 말할 수 있습니다.

자바는 교활한 일을한다. 열거 형 값을 참조 할 때 많은 매크로를 사용하여 열거 형 클래스를 정상적인 클래스로 취급합니다. 열거 형을 사용하는 Java 클래스에 case 문이 있으면 열거 형 참조를 정수로 바꿉니다. 문자열로 이동해야하는 경우 각 클래스에서 사용하는 서수로 색인화 된 문자열 배열을 작성합니다. 권투에 저축 할 것으로 생각됩니다.

이 디 컴파일러를 다운로드하면 클래스를 만드는 방법과 통합하는 방법을 볼 수 있습니다. 솔직히 매혹적인 것. 나는 열거 형 클래스를 사용하지 않았습니다. 왜냐하면 그것이 상수 배열에 대해 부풀어 오른 것으로 생각했기 때문입니다. C #에서 사용할 수있는 제한된 방법보다 낫습니다.

http://members.fortunecity.com/neshkov/dj.html- 자바 디 컴파일러


0

Java의 열거 형은 C # 열거 형보다 훨씬 복잡하므로 더 강력합니다. 그것은 컴파일 타임의 또 다른 컴파일 타임 설탕이기 때문에 실제 응용 프로그램에서 제한된 사용으로 언어를 포함시킬 가치가 있는지 궁금합니다. 때로는 사소한 기능을 포함하라는 압력을 포기하는 것보다 언어로 물건을 보관하는 것이 더 어렵습니다.


2
나는 정중하게 동의하지 않습니다. Java 1.5 열거 형은 여러 언어를 사용하여 불연속 이름 지정된 항목의 개별 세트를 처리하는 문제에 대한 OO 중심 솔루션을 구현하는 데 여러 번 사용했습니다.
오우거

1
당신은 할 수 있습니다. 그러나 스마트 한 '스위치'언어 통합 이외에도 나머지 기능은 위의 예와 같이 C # 또는 Java 자체로 쉽게 복제 할 수 있습니다.
dmihailescu

@dmihailescu "Java의 enum은 C #보다 훨씬 복잡합니다. 따라서 Java를 삭제했습니다 ..."
Mukus

0
//Review the sample enum below for a template on how to implement a JavaEnum.
//There is also an EnumSet implementation below.

public abstract class JavaEnum : IComparable {
    public static IEnumerable<JavaEnum> Values {
        get {
            throw new NotImplementedException("Enumeration missing");
        }
    }

    public readonly string Name;

    public JavaEnum(string name) {
        this.Name = name;
    }

    public override string ToString() {
        return base.ToString() + "." + Name.ToUpper();
    }

    public int CompareTo(object obj) {
        if(obj is JavaEnum) {
            return string.Compare(this.Name, ((JavaEnum)obj).Name);
        } else {
            throw new ArgumentException();
        }
    }


    //Dictionary values are of type SortedSet<T>
    private static Dictionary<Type, object> enumDictionary;
    public static SortedSet<T> RetrieveEnumValues<T>() where T : JavaEnum {
        if(enumDictionary == null) {
            enumDictionary = new Dictionary<Type, object>();
        }
        object enums;
        if(!enumDictionary.TryGetValue(typeof(T), out enums)) {
            enums = new SortedSet<T>();
            FieldInfo[] myFieldInfo = typeof(T).GetFields(BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public);
            foreach(FieldInfo f in myFieldInfo) {
                if(f.FieldType == typeof(T)) {
                    ((SortedSet<T>)enums).Add((T)f.GetValue(null));
                }
            }
            enumDictionary.Add(typeof(T), enums);
        }
        return (SortedSet<T>)enums;
    }
}


//Sample JavaEnum
public class SampleEnum : JavaEnum {
    //Enum values
    public static readonly SampleEnum A = new SampleEnum("A", 1);
    public static readonly SampleEnum B = new SampleEnum("B", 2);
    public static readonly SampleEnum C = new SampleEnum("C", 3);

    //Variables or Properties common to all enums of this type
    public int int1;
    public static int int2 = 4;
    public static readonly int int3 = 9;

    //The Values property must be replaced with a call to JavaEnum.generateEnumValues<MyEnumType>() to generate an IEnumerable set.
    public static new IEnumerable<SampleEnum> Values {
        get {
            foreach(var e in JavaEnum.RetrieveEnumValues<SampleEnum>()) {
                yield return e;
            }
            //If this enum should compose several enums, add them here
            //foreach(var e in ChildSampleEnum.Values) {
            //    yield return e;
            //}
        }
    }

    public SampleEnum(string name, int int1)
        : base(name) {
        this.int1 = int1;
    }
}


public class EnumSet<T> : SortedSet<T> where T : JavaEnum {
    // Creates an enum set containing all of the elements in the specified element type.
    public static EnumSet<T> AllOf(IEnumerable<T> values) {
        EnumSet<T> returnSet = new EnumSet<T>();
        foreach(T item in values) {
            returnSet.Add(item);
        }
        return returnSet;
    }

    // Creates an enum set with the same element type as the specified enum set, initially containing all the elements of this type that are not contained in the specified set.
    public static EnumSet<T> ComplementOf(IEnumerable<T> values, EnumSet<T> set) {
        EnumSet<T> returnSet = new EnumSet<T>();
        foreach(T item in values) {
            if(!set.Contains(item)) {
                returnSet.Add(item);
            }
        }
        return returnSet;
    }

    // Creates an enum set initially containing all of the elements in the range defined by the two specified endpoints.
    public static EnumSet<T> Range(IEnumerable<T> values, T from, T to) {
        EnumSet<T> returnSet = new EnumSet<T>();
        if(from == to) {
            returnSet.Add(from);
            return returnSet;
        }
        bool isFrom = false;
        foreach(T item in values) {
            if(isFrom) {
                returnSet.Add(item);
                if(item == to) {
                    return returnSet;
                }
            } else if(item == from) {
                isFrom = true;
                returnSet.Add(item);
            }
        }
        throw new ArgumentException();
    }

    // Creates an enum set initially containing the specified element(s).
    public static EnumSet<T> Of(params T[] setItems) {
        EnumSet<T> returnSet = new EnumSet<T>();
        foreach(T item in setItems) {
            returnSet.Add(item);
        }
        return returnSet;
    }

    // Creates an empty enum set with the specified element type.
    public static EnumSet<T> NoneOf() {
        return new EnumSet<T>();
    }

    // Returns a copy of the set passed in.
    public static EnumSet<T> CopyOf(EnumSet<T> set) {
        EnumSet<T> returnSet = new EnumSet<T>();
        returnSet.Add(set);
        return returnSet;
    }

    // Adds a set to an existing set.
    public void Add(EnumSet<T> enumSet) {
        foreach(T item in enumSet) {
            this.Add(item);
        }
    }

    // Removes a set from an existing set.
    public void Remove(EnumSet<T> enumSet) {
        foreach(T item in enumSet) {
            this.Remove(item);
        }
    }
}

0

각 열거 형 값에 대해 고급 데이터가있는 인스턴스를 보유하는 각 열거 형 유형에 대해 유틸리티 클래스를 사용할 수도 있습니다.

public enum Planet
{
    MERCURY,
    VENUS
}

public class PlanetUtil
{
    private static readonly IDictionary<Planet, PlanetUtil> PLANETS = new Dictionary<Planet, PlanetUtil();

    static PlanetUtil()
    {
        PlanetUtil.PLANETS.Add(Planet.MERCURY, new PlanetUtil(3.303e+23, 2.4397e6));
        PlanetUtil.PLANETS.Add(Planet.VENUS, new PlanetUtil(4.869e+24, 6.0518e6));
    }

    public static PlanetUtil GetUtil(Planet planet)
    {
        return PlanetUtil.PLANETS[planet];
    }

    private readonly double radius;
    private readonly double mass;

    public PlanetUtil(double radius, double mass)
    {
        this.radius = radius;
        this.mass = mass;
    }

    // getter
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.