값을 변경하지 않고 Enum 유형의 기본값 선택


208

C #에서 Enum 유형을 속성으로 장식하거나 값을 변경하지 않고 기본값을 지정하기 위해 다른 작업을 수행 할 수 있습니까? 필요한 숫자는 어떤 이유로 든 석재로 설정 될 수 있으며 여전히 기본값을 제어하는 ​​것이 편리합니다.

enum Orientation
{
    None = -1,
    North = 0,
    East = 1,
    South = 2,
    West = 3
}

Orientation o; // Is 'North' by default.

int ?, double? 등의 기본값을 변경할 수 있습니까?
— AR

2
@AR 과거에 대한 공격은 없지만, 열거 형을 ints 와 비교하는 것은 의미가 없습니다 . 단순히 숫자 유형으로 구현되기 때문입니다. 열거 형을 문자열로 구현할 수 있으며 유용성을 변경하지는 않습니다. 나는 여기서의 대답이 C # 언어 표현의 한계라고 생각한다. 제한은 "제한된 세트와 값을 구별하는"아이디어에 내재되어 있지 않습니다.
— jpaugh

1
@jpaugh 나는 열거 형을 int와 추상적으로 비교하지 않습니다. 기본값을 변경하는 것이 의미가없는 다른 데이터 (문자열 및 기타 참조 포함) 유형의 예를 제공합니다. 제한이 아니라 디자인 기능입니다. 일관성은 당신의 친구입니다 :)
— AR

@AR 포인트 촬영. 나는 enum타입 레벨 구조, 특히 합계 유형 으로 s를 생각하는 데 너무 많은 시간을 소비한다고 가정 합니다 (또는 여기를 참조하십시오 . 즉, 각 열거 형을 고유 한 유형으로 간주 하십시오 . 즉, 해당 유형의 모든 값이 다른 모든 열거 형 값과 구별됩니다. 이러한 사고 방식에서 열거 형이 값 을 공유 하는 것은 불가능 하며 실제로이 추상화 0는 주어진 열거 형에 대한 기본값 이 유효하거나 유효하지 않을 수 있으며 모든 열거 형에 구두 혼입되어 있다고 생각하면 구분됩니다 .
— jpaugh

예, 저는 차별적 인 노조에 익숙합니다. C # 열거 형은 그렇지 않으므로 그렇게 높은 (그리고 잘못된) 수준으로 생각하는 것이 도움이되는지 모르겠습니다. 'sum type'은 확실히 장점이 있지만 enum과 enum도 있습니다 (적절한 값이 제공된다고 가정). 예 : myColor = Colors.Red | 색상. 파란색. 내 주요 요점은 c #에 대한 합계 유형을 원한다면 열거 형 개념의 용도를 바꾸지 않고 하나를 만드십시오.
— AR

답변:


349

enum(실제로 모든 값 유형) 의 기본값 은 0입니다 enum. 해당 값이 유효하지 않은 경우에도 마찬가지입니다 . 변경할 수 없습니다.


13
int의 기본값은 42가되도록 질문을 바꾸십시오. 그 소리가 어떻게 들리는 지 생각해보십시오. 메모리는 런타임에 비워 지고, 열거 형은 구조체를 기억합니다
— ShuggyCoUk

3
@DougS 1. 아니요,하지만 당신이 틀렸다는 것을 인정하는 것입니다. 2. 그는 의견 공의로 명성을 얻지 못했다.
— Aske B.

7
의견은이 답변에 대해 의심스럽게 만들었으므로 테스트 하고이 답변이 확실히 맞는지 확인했습니다.
— Ian Newson

1
@JamesCurran 그러나 열거 형에 0 값을 사용하지 않으면 "MyProjectName.dll에서 'System.NullReferenceException'유형의 예외가 발생했지만 사용자 코드에서 처리되지 않았습니다. 추가 정보 : 개체 참조가 개체의 인스턴스로 설정되지 않았습니다." 오류. 고치는 방법? 참고 : 열거 형 설명을 표시하기 위해 확장 방법을 사용하지만 이 페이지에
— Jack

64

열거 형의 기본값은 0입니다. 따라서 하나의 열거자를 기본값으로 설정하려면 해당 열거자를 0으로 설정하고 다른 모든 열거자를 0이 아닌 값으로 설정하십시오 (여러 열거자가있는 경우 값이 0 인 첫 번째 열거자가 해당 열거의 기본값이 됨). 0 값으로).

enum Orientation
{
    None = 0, //default value since it has the value '0'
    North = 1,
    East = 2,
    South = 3,
    West = 4
}

Orientation o; // initialized to 'None'

열거 자에 명시적인 값이 필요하지 않은 경우 "기본적으로 첫 번째 열거자는 0 값을 가지며 각 연속 열거 자의 값은 다음과 같이 증가하므로 첫 번째 열거자는 기본 열거자가 될 것이어야합니다. 1." ( C # 참조 )

enum Orientation
{
    None, //default value since it is the first enumerator
    North,
    East,
    South,
    West
}

Orientation o; // initialized to 'None'

38

0이 올바른 기본값으로 작동하지 않으면 구성 요소 모델을 사용하여 열거 형에 대한 해결 방법을 정의 할 수 있습니다.

[DefaultValue(None)]
public enum Orientation
{
     None = -1,
     North = 0,
     East = 1,
     South = 2,
     West = 3
 }

public static class Utilities
{
    public static TEnum GetDefaultValue<TEnum>() where TEnum : struct
    {
        Type t = typeof(TEnum);
        DefaultValueAttribute[] attributes = (DefaultValueAttribute[])t.GetCustomAttributes(typeof(DefaultValueAttribute), false);
        if (attributes != null &&
            attributes.Length > 0)
        {
            return (TEnum)attributes[0].Value;
        }
        else
        {
            return default(TEnum);
        }
    }
}

그리고 당신은 전화 할 수 있습니다 :

Orientation o = Utilities.GetDefaultValue<Orientation>();
System.Diagnostics.Debug.Print(o.ToString());

참고 : 파일 맨 위에 다음 줄을 포함해야합니다.

using System.ComponentModel;

이것은 열거 형의 실제 C # 언어 기본값을 변경하지 않지만 원하는 기본값을 표시하고 얻는 방법을 제공합니다.


죄송합니다. 작동하지 않습니다. 더 많은 정보를 추가 할 수 있습니까? System.ComponentModel을 사용하여 행을 추가해야합니다. 그런 다음 유틸리티 클래스에서 GetDefaultEnum () 함수를 작성하십시오. 사용중인 .net 버전은 무엇입니까?
— David

3
컴포넌트 모델 속성 및 클린 솔루션의 재사용에 +1 else명세서 의 마지막 줄 을 다음과 같이 변경하는 것이 좋습니다 return default(TEnum);. 주먹, 그것은 느린 Enum.GetValues(...).***호출 을 줄이며 , 두 번째 (더 중요한 것)는 열거 형이 아닌 모든 유형에 일반적입니다. 또한 열거 형에만 사용되는 코드를 제한하지 않으므로 열거 형 이외의 유형을 사용할 때 실제로 예외가 해결됩니다.
— Ivaylo Slavov

1
이것은 질문의 맥락에서 기본값 속성의 오용일 수 있습니다. 질문은 자동으로 초기화 된 값에 관한 것이며 제안 된 솔루션으로 변경되지 않습니다. 이 속성은 비주얼 디자이너의 기본값이 초기 값과 다른 경우에 사용됩니다. 비주얼 디자이너의 질문을하는 사람은 언급하지 않습니다.
— David Burg

2
MSDN 설명서에는 ComponentModel 또는 DefaultAttribute가 "시각적 디자이너"전용 기능이라는 것이 없습니다. 받아 들여진 대답은 다음과 같습니다. 짧은 대답은 열거 형의 기본값을 0 값 이외의 다른 값으로 다시 정의하는 "아니오, 불가능"입니다. 이 답변은 해결 방법입니다.
— David

17

열거의 기본값은 열거가 0에 해당하는 것입니다. 나는 이것이 속성이나 다른 방법으로 변경 될 수 있다고 생각하지 않습니다.

(MSDN의 말 : "열거 E의 기본값은 식 (E) 0에 의해 생성 된 값입니다.")


13
엄밀히 말하면이 값으로 열거 할 필요조차 없습니다. 여전히 기본값은 0입니다.
— Marc Gravell

11

할 수는 없지만 원하는 경우 속임수를 쓸 수 있습니다. :)

    public struct Orientation
    {
        ...
        public static Orientation None = -1;
        public static Orientation North = 0;
        public static Orientation East = 1;
        public static Orientation South = 2;
        public static Orientation West = 3;
    }

이 구조체를 간단한 열거 형으로 사용합니다. 트릭 자체를 사용하기 위해
기본적
으로 pa == Orientation.East (또는 원하는 값)를 만들 수있는 경우 int에서 코드로 변환해야합니다.
구현이 있습니다.

        #region ConvertingToEnum
        private int val;
        static Dictionary<int, string> dict = null;

        public Orientation(int val)
        {
            this.val = val;
        }

        public static implicit operator Orientation(int value)
        {
            return new Orientation(value - 1);
        }

        public static bool operator ==(Orientation a, Orientation b)
        {
            return a.val == b.val;
        }

        public static bool operator !=(Orientation a, Orientation b)
        {
            return a.val != b.val;
        }

        public override string ToString()
        {
            if (dict == null)
                InitializeDict();
            if (dict.ContainsKey(val))
                return dict[val];
            return val.ToString();
        }

        private void InitializeDict()
        {
            dict = new Dictionary<int, string>();
            foreach (var fields in GetType().GetFields(BindingFlags.Public | BindingFlags.Static))
            {
                dict.Add(((Orientation)fields.GetValue(null)).val, fields.Name);
            }
        } 
        #endregion

묵시적 변환 연산자에서 value + 1, 그렇지 않으면 이제는 default(Orientation)리턴 이 필요 합니다 East. 또한 생성자를 비공개로 만듭니다. 좋은 접근 방식.
— nawfal

10

도움이 될 수있는 또 하나의 방법은 일종의 "별명"을 사용하는 것입니다. 예를 들면 다음과 같습니다.

public enum Status
{
    New = 10,
    Old = 20,
    Actual = 30,

    // Use Status.Default to specify default status in your code. 
    Default = New 
}

1
그러나 다른 답변에서 이미 언급했듯이 열거 형의 기본값은 0입니다. 귀하의 경우 표현식 의 값은이므로 Status s = default(Status);상태 멤버가 아닙니다 . 후자는 열거 형을 정수로 캐스트 할 수 있으므로 직접 작성하는 것이 유효하지만 프레임 워크는 열거 형이 항상 유효한 멤버로 직렬화 해제되도록하기 때문에 직렬화 해제 중에 실패합니다. 행 을로 변경하면 코드가 완벽하게 유효합니다 . s(Staus) 0New = 10New = 0
— Ivaylo Slavov

1
예. New = 0이 작동합니다. 나는 열거 형 멤버를 명시 적으로 설정하지 않는 것을 개인적으로 피할 것입니다.
— Dmitry Pavlov

7

실제로 enum의 기본값은 enum값 의 첫 번째 요소 입니다.0 .

예를 들어 :

public enum Animals
{
    Cat,
    Dog,
    Pony = 0,
}
//its value will actually be Cat not Pony unless you assign a non zero value to Cat.
Animals animal;

9
그러나,이 경우에 "포니", "고양이"(예를 들어, IS Console.WriteLine(Animals.Pony);인쇄 "고양이")
— 제임스 쿠란

16
실제로 다음 중 하나를 수행해야합니다. 값을 지정하지 않거나 모든 값을 지정하거나 첫 번째 정의 된 멤버의 값만 지정하십시오. Cat은 값이없고 첫 번째 값이므로 자동으로 0으로 설정합니다. Dog는 값이없고 자동으로 PreviousValue + 1로 설정합니다. 1입니다. Poney에는 값이 있습니다. 값을 그대로 두십시오. 따라서 Cat = Pony = 0, Dog = 1입니다. {Cat, Dog, Pony = 0, Frog}가 있으면 Dog = Frog = 1입니다.
— user276648

4

The default value of enum is the enummember equal to 0 or the first element(if value is not specified) ...하지만 프로젝트에서 열거 형을 사용하여 중요한 문제에 직면했으며 아래에서 무언가를 수행하여 극복했습니다 ... 내 요구가 수업 수준과 어떻게 관련되어 있는지 ...

    class CDDtype
    {
        public int Id { get; set; }
        public DDType DDType { get; set; }

        public CDDtype()
        {
            DDType = DDType.None;
        }
    }    


    [DefaultValue(None)]
    public enum DDType
    {       
        None = -1,       
        ON = 0,       
        FC = 1,       
        NC = 2,       
        CC = 3
    }

예상 결과를 얻을

    CDDtype d1= new CDDtype();
    CDDtype d2 = new CDDtype { Id = 50 };

    Console.Write(d1.DDType);//None
    Console.Write(d2.DDType);//None

이제이 값이 DB에서 오는 경우 ....이 시나리오에서 좋아요 ... 아래 함수에서 값을 전달하면 값이 열거 형으로 변환됩니다 ... 아래 함수는 다양한 시나리오를 처리하고 일반적입니다 ... 매우 빠른 ..... :)

    public static T ToEnum<T>(this object value)
    {
        //Checking value is null or DBNull
        if (!value.IsNull())
        {
            return (T)Enum.Parse(typeof(T), value.ToStringX());
        }

        //Returanable object
        object ValueToReturn = null;

        //First checking whether any 'DefaultValueAttribute' is present or not
        var DefaultAtt = (from a in typeof(T).CustomAttributes
                          where a.AttributeType == typeof(DefaultValueAttribute)
                          select a).FirstOrNull();

        //If DefaultAttributeValue is present
        if ((!DefaultAtt.IsNull()) && (DefaultAtt.ConstructorArguments.Count == 1))
        {
            ValueToReturn = DefaultAtt.ConstructorArguments[0].Value;
        }

        //If still no value found
        if (ValueToReturn.IsNull())
        {
            //Trying to get the very first property of that enum
            Array Values = Enum.GetValues(typeof(T));

            //getting very first member of this enum
            if (Values.Length > 0)
            {
                ValueToReturn = Values.GetValue(0);
            }
        }

        //If any result found
        if (!ValueToReturn.IsNull())
        {
            return (T)Enum.Parse(typeof(T), ValueToReturn.ToStringX());
        }

        return default(T);
    }

주어진 질문에 의도적으로 대답하지 않은 경우 -1입니다. 이것은 명백한 숙제 문제가 아니며 의도적으로 대답하지 않는 유일한 경우입니다.
— Xynariz

1
@ Xynariz .. 죄송합니다 .. 내 의도는 다른 방법으로 솔루션을 제공하는 것이기 때문에 실수로 부정적인 의견이었습니다 ... 그래서 내가 의견을 변경했습니다 ... : D
— Moumit

2

열거 유형의 기본값은 0입니다.

  • " 기본적으로 첫 번째 열거자는 0 값을 가지며 연속 된 각 열거 자의 값은 1 씩 증가합니다. "

  • " 값 유형 enum에는 식 (E) 0에 의해 생성 된 값이 있습니다. 여기서 E는 열거 형 식별자입니다. "

당신은 C #을 열거에 대한 문서를 확인하실 수 있습니다 여기에 , 그리고 C # 기본값 테이블에 대한 설명서 여기 .


1

Default enum을 가장 작은 값을 가진 enum으로 정의하면 다음을 사용할 수 있습니다.

public enum MyEnum { His = -1, Hers = -2, Mine = -4, Theirs = -3 }

var firstEnum = ((MyEnum[])Enum.GetValues(typeof(MyEnum)))[0];

firstEnum == Mine.

열거 형의 값이 0이라고 가정하지 않습니다.


0

기본값은 정의에서 첫 번째입니다. 예를 들면 다음과 같습니다.

public enum MyEnum{His,Hers,Mine,Theirs}

Enum.GetValues(typeOf(MyEnum)).GetValue(0);

이것은 돌아올 것이다 His


ㅋ; "default value"는 0입니다. 그러나! 그는 기본값 "zero"는 첫 번째 명명 된 값의 기본 기호 일 뿐이라고 말한다. ! 다시 말해 언어는 당신 대신에 기본값을 선택합니다. 이것은 또한 0이 int ..의 기본값 인 경우에도 발생합니다. lol
— user1953264

0
enum Orientations
{
    None, North, East, South, West
}
private Orientations? _orientation { get; set; }

public Orientations? Orientation
{
    get
    {
        return _orientation ?? Orientations.None;
    }
    set
    {
        _orientation = value;
    }
}

이 속성을 null로 설정하면 Orientations.None이 반환됩니다. _orientation 속성은 기본적으로 null입니다.


-5
[DefaultValue(None)]
public enum Orientation
{
    None = -1,
    North = 0,
    East = 1,
    South = 2,
    West = 3
}

그런 다음 코드에서 사용할 수 있습니다

public Orientation GetDefaultOrientation()
{
   return default(Orientation);
} 

14
/! \ WRONG /! \ DefaultValueAttribute는 실제로 값을 설정하지 않으며 단지 정보 목적으로 만 사용됩니다. 그런 다음 열거 형, 필드, 속성, ...에 해당 속성이 있는지 확인하는 것은 사용자의 몫입니다. PropertyGrid는이를 사용하여 마우스 오른쪽 버튼을 클릭하고 "재설정"을 선택할 수 있습니다. 또한 기본값을 사용하지 않는 경우 텍스트는 굵게 표시됩니다. 그러나 여전히 수동으로 속성을 원하는 기본값으로 설정해야합니다.
— user276648
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.