열거 형은 0 또는 1로 시작해야합니까?


136

다음 Enum을 정의했다고 상상해보십시오.

public enum Status : byte
{
    Inactive = 1,
    Active = 2,
}

열거 형을 사용하는 가장 좋은 방법은 무엇입니까? 1위의 예제 와 같이 시작 하거나 다음 과 같이 0명시 적 값없이 시작 해야합니다 .

public enum Status : byte
{
    Inactive,
    Active
}

13
정말로 명시 적으로 번호를 매길 필요가 있습니까?
Yuck

164
열거 형은 이와 같은 것들이 중요하지 않도록 만들어졌습니다.
BoltClock

9
@ 다니엘-아아! 부울 을 생각할 때 부울을 사용하는 것보다 부울을 사용 한다고 생각할 때 열거 형 을 사용하는 것이 좋습니다.
AAT

22
물론 FileNotFound 값 때문에
@Daniel

5
xkcd.com/163 은 인덱스를 배열하는 것보다 enum에 더 잘 적용됩니다.
leftaroundabout

답변:


161

프레임 워크 설계 지침 :

✔️ DO는 간단한 열거 형에 0 값을 제공합니다.

"없음"과 같은 값을 호출하십시오. 이러한 값이이 특정 열거 형에 적합하지 않은 경우 열거 형의 가장 일반적인 기본값에는 기본 값인 0이 할당되어야합니다.

프레임 워크 디자인 가이드 라인 / 플래그 열거 디자인 :

❌ 값이 "모든 플래그가 지워짐"을 나타내지 않고 다음 지침에 규정 된대로 적절하게 명명되지 않은 경우 플래그 열거 형 값 0을 사용하지 마십시오.

✔️ DO 열거의 0 값 이름을 None으로 지정하십시오. 플래그 열거의 경우, 값은 항상 "모든 플래그가 지워짐"을 의미해야합니다.


28
일찍 실패 : '없음'이 적절하지 않지만 논리적 기본값이없는 경우 여전히 사용되지 않는 값을 0으로 설정하고 '없음'또는 '잘못된'이라고 부릅니다. 해당 열거의 클래스 멤버가 올바르게 초기화되지 않으면 초기화되지 않은 값을 쉽게 찾을 수 있으며 switchdefault에서을 던지는 섹션으로 이동합니다 InvalidEnumArgumentException. 그렇지 않으면 프로그램이 의도하지 않게 열거의 0 값으로 계속 실행될 수 있으며, 이는 유효하고 눈에 띄지 않을 수 있습니다.
Allon Guralnek

1
@Allon 알고있는 열거 형 값만 제공 한 다음 setter 및 / 또는 생성자에서 유효하지 않은 값을 확인하는 것이 좋습니다. 이렇게하면 알려지지 않은 시간 동안 유효하지 않은 데이터가있는 객체가 존재하도록하고 나중에 알아내는 것이 아니라 일부 코드가 올바르게 작동하지 않는 경우 즉시 알 수 있습니다. '없음'이 유효한 상태를 나타내지 않으면 사용해서는 안됩니다.
wprl

@SoloBold : 생성자에서 열거 형 클래스 멤버를 초기화하는 것을 잊지 않는 경우처럼 들립니다. 초기화를 잊어 버렸거나 유효성 검사를 잊어 버린 경우에는 많은 양의 유효성 검사가 도움이되지 않습니다. 또한 생성자가 없지만 간단한 객체 이니셜 라이저를 사용 하는 간단한 DTO 클래스가 있습니다. 이러한 버그를 찾아내는 것은 매우 고통 스러울 수 있습니다. 그럼에도 불구하고 사용되지 않은 열거 값을 추가하면 추악한 API가됩니다. 대중 소비를 위해 설계된 API에서는 피할 것입니다.
Allon Guralnek

@Allon 좋은 지적이지만 setter가 호출되지 않은 경우 setter 함수에서 열거 형을 확인하고 getter에서 던져야한다고 주장합니다. 이렇게하면 하나의 실패 지점이 있으며 항상 유효한 값을 갖도록 현장을 계획 할 수 있으므로 설계 및 코드가 간단 해집니다. 어쨌든 내 두 센트.
wprl

@SoloBold : 15 개의 자동 구현 된 속성을 가진 DTO 클래스를 상상해보십시오. 몸의 길이는 15 줄입니다. 이제 규칙적인 속성을 가진 같은 클래스를 상상해보십시오. 검증 로직을 추가하기 전에 최소 180 줄입니다. 이 클래스는 내부적으로 데이터 전송 목적으로 만 사용됩니다. 15 개 라인 클래스 또는 180 개 이상의 라인 클래스 중 어느 것을 유지 하시겠습니까? 간결함은 그 가치가 있습니다. 그러나 여전히 우리의 두 스타일은 모두 정확하며 단순히 다릅니다. (이것이 AOP가 스윕하고 논쟁의 양쪽에서이기는 곳이라고 생각합니다).
Allon Guralnek

66

글쎄, 나는 대답을 명시 적으로 번호를 매기 지 않는다고 말하는 대부분의 답변에 동의하지 않는 것 같습니다. 나는 항상 명시 적으로 번호를 매기지만, 대부분의 경우 정수 값으로 저장된 데이터 스트림에 유지하기 때문입니다. 명시 적으로 값을 추가하지 않고 새 값을 추가하면 직렬화가 중단되고 오래 지속되는 개체를 정확하게로드 할 수 없습니다. 이러한 값의 영구 저장소 유형을 수행하려는 경우 값을 명시 적으로 설정하는 것이 좋습니다.


9
+1, 동의하지만 코드가 외부 이유로 인해 정수에 의존하는 경우에만 해당됩니다 (예 : 직렬화). 다른 곳에서는 프레임 워크가 제대로 작동하도록해야합니다. 내부적으로 정수 값에 의존한다면 아마도 잘못된 일을하고있을 것입니다 (프레임 워크가 작동하도록하십시오).
Matthew Scharley

3
나는 열거 형의 텍스트를 유지하고 싶습니다. 데이터베이스를 훨씬 더 유용한 imo로 만듭니다.
Dave

2
일반적으로 직렬화 된 경우에도 명시 적으로 값을 설정할 필요가 없습니다. 항상 끝에 새로운 값을 추가하십시오. 직렬화 문제를 해결합니다. 그렇지 않으면 데이터 저장소의 버전 관리가 필요할 수 있습니다 (예 : 값을 읽거나 쓸 때 동작을 변경하기위한 버전이 포함 된 파일 헤더) (또는 메모리 패턴 참조)
Beachwalker

4
@Dave : 열거 형 텍스트가 신성한 문서를 설명하지 않는 한, 미래의 프로그래머가 이름을 더 명확하게 또는 일부 명명 규칙에 맞게 조정하기로 결정하면 실패 할 수 있습니다.
supercat

1
@ pstrjds : 그것은 문체 적 인 트레이드 오프라고 생각합니다-디스크 공간은 저렴하지만 열거 형 값 사이를 지속적으로 변환하는 데 소요되는 시간과 db를 검색하는 데 드는 시간은 상대적으로 비쌉니다 (아마도 데이터베이스 또는 이와 유사한 것에 대해보고 도구 설정이있는 경우) . abotu 공간이 걱정된다면 최신 SQL Server 버전으로 데이터베이스를 압축 할 수 있습니다. 즉, "SomeEnumTextualValue"가 1000 번 발생하면 더 이상 공간이 거의 사용되지 않습니다. 물론 이것은 모든 프로젝트에서 작동하지는 않습니다. 트레이드 오프입니다. 대역폭 최적화에 대한 걱정은 아마도 조기 최적화와 같은 것 같습니다.
Dave

15

Enum은 값 유형이며 명시 적으로 초기화되지 않은 경우 기본값 (예 : 클래스의 Enum 필드)은 0입니다.

따라서 일반적으로 정의 된 상수 (예 : 알 수 없음)로 0을 원합니다.

예를 들어, Inactive기본값이 되려면 값이 0이어야합니다. 그렇지 않으면 상수 추가를 고려할 수 있습니다 Unknown.

일부 사람들은 상수 값을 명시 적으로 지정하지 않는 것이 좋습니다. 대부분의 경우 좋은 조언이지만, 그렇게하고 싶을 때가 있습니다.

  • 플래그 열거 형

  • 외부 시스템과의 상호 운용에 사용되는 값을 가진 열거 형 (예 : COM)


명시 적으로 값을 설정 하지 않으면 플래그 열거 형이 훨씬 읽기 쉽다는 것을 알았습니다 . -또한 컴파일러가 이진 수학을 수행하게하는 오류가 줄어 듭니다. (즉 [Flags] enum MyFlags { None = 0, A, B, Both = A | B, /* etc. */ },보다 읽기 쉬운 방법 [Flags] enum MyFlags { None = 0, A = 1, B = 2, Both = 3, /* etc */ }입니다.)
BrainSlugs83

1
@ BrainSlugs83 - 나는 그것이 일반적인 경우에 도움이 될 것입니다 표시되지 않습니다 - 예를 들면 [Flags] enum MyFlags { None=0, A, B, C } 초래 [Flags] enum MyFlags { None=0, A=1, B=2, C=3 }플래그 열거 형에 대한 당신이 일반적으로 C = 4 원하는 것 반면.
Joe

14

특별한 이유가 없다면, 열거 형을 기본값 인 0으로 시작하십시오.

public enum Status : byte
{
    Inactive,
    Active
}

6

가장 좋은 방법은 번호를 지정하지 않고 암시 적으로 만드는 것입니다. 0에서 시작합니다. 암시 적이므로 항상 따라야하는 언어 기본 설정 :)


6

부울 타입 열거 형을 0으로 시작합니다.

"Inative"가 "Inactive"이외의 것을 의미하지 않는 한 :)

이것은 그 표준을 유지합니다.


6

사용 방법에 따라 다릅니다. 열거를 플래그 지정하려면 다음 None과 같이 값에 0을 지정하는 것이 좋습니다 .

[Flags]
enum MyEnum
{
    None = 0,
    Option1 = 1,
    Option2 = 2,
    Option3 = 4,
    All = Option1 | Option2 | Option3,
}

열거 형이 데이터베이스 조회 테이블에 매핑 될 가능성이 높으면 1로 시작합니다. 전문적으로 작성된 코드에는별로 중요하지 않지만 가독성이 향상됩니다.

다른 경우에는 0 또는 1로 시작하는지 여부를 신경 쓰지 않고 그대로 둡니다.


5

당신은 원시 값을 사용하는 좋은 이유가없는 한, 당신은 오직 암시 적 값을 사용하고 그들을 참조해야 Status.Active하고 Status.Inactive.

중요한 것은 플랫 파일이나 DB에 데이터를 저장하거나 다른 사람이 만든 플랫 파일이나 DB를 사용하고 싶을 수 있습니다. 직접 만드는 경우 번호 매기기가 Enum의 용도와 일치하도록 만드십시오.

데이터가 자신의 것이 아닌 경우 물론 원래 개발자가 번호 매기기 체계로 사용한 것을 사용하려고합니다.

Enum을 플래그 집합으로 사용하려는 경우 다음과 같은 간단한 규칙이 있습니다.

enum Example
{
  None      = 0,            //  0
  Alpha     = 1 << 0,       //  1
  Beta      = 1 << 1,       //  2
  Gamma     = 1 << 2,       //  4
  Delta     = 1 << 3,       //  8
  Epsilon   = 1 << 4,       // 16
  All       = ~0,           // -1
  AlphaBeta = Alpha | Beta, //  3
}

값은 2의 거듭 제곱이어야하며 비트 시프트 연산을 사용하여 표현할 수 있습니다. None분명히되어야 0하지만 All덜 분명하다 -1. ~0이진의 부정 인 0에 모든 비트 세트를 갖는 다수의 결과 1, 의 값을 나타낸다-1 . 복합 플래그 (종종 편의상 사용됨)의 경우 비트 단위 또는 연산자를 사용하여 다른 값을 병합 할 수 있습니다 |.


3

숫자를 할당하지 마십시오. 사용하는 것처럼 사용하십시오.


3

지정하지 않으면 번호 매기기는 0에서 시작합니다.

열거 형은 종종 문자열이 아닌 int로 직렬화되고 저장되므로 명시 적이어야합니다.

데이터베이스에 저장된 열거 형의 경우 유지 관리 중 이동 및 재 할당을 방지하기 위해 항상 옵션에 번호를 매 깁니다.

Microsoft에 따르면 권장되는 규칙은 첫 번째 0 옵션을 사용하여 초기화되지 않은 또는 가장 일반적인 기본값을 나타냅니다.

다음은 0 대신 1에서 번호를 시작하는 바로 가기입니다.

public enum Status : byte
{
    Inactive = 1,
    Active
}

열거 형 값에 비트 연산자를 사용하기 위해 플래그 값을 설정하려면 0 값에서 번호 매기기를 시작하지 마십시오.


2

1에서 시작하면 쉽게 많은 것을 얻을 수 있습니다.

{
    BOX_THING1     = 1,
    BOX_THING2     = 2,
    BOX_NUM_THING  = BOX_THING2
};

0에서 시작하면 초기화되지 않은 것들에 대한 값으로 첫 번째 것을 사용하십시오.

{
    BOX_NO_THING   = 0,
    BOX_THING1     = 1,
    BOX_THING2     = 2,
    BOX_NUM_THING  = BOX_THING2
};

5
미안, 조나단 저는이 제안이 제 생각에 "구식 학교"라고 생각합니다. 이것은 열거 형에 대한 추가 정보를 "포함"하는 빠른 솔루션으로 괜찮지 만 더 큰 시스템에서는 좋은 방법이 아닙니다. 사용 가능한 값 수 등에 대한 정보가 필요한 경우 열거 형을 사용하면 안됩니다. BOX_NO_THING1은 어떻습니까? BOX_NO_THING + 1을 제공 하시겠습니까? 열거 형은 다음과 같은 용도로 사용되어야합니다. "말하는"이름으로 표시되는 특정 (int) 값.
Beachwalker

흠. MicrosoftBumpyCaseWithLongNames 대신 모든 대문자를 사용했기 때문에 오래된 학교라고 가정합니다. 비록 열거 형 XyzNumDefsInMyEnum 정의에 도달 할 때까지 루프보다 반복자를 사용하는 것이 좋습니다.
Jonathan Cline IEEE

이것은 C #에서 다양한 방식으로 끔찍한 관행입니다. 이제 열거 형 수를 올바르게 가져 오거나 올바른 방법으로 열거하려고하면 여분의 중복 개체가 생깁니다. 또한 .ToString () 호출을 잠재적으로 모호하게 만듭니다 (현대 직렬화를 촉진).
BrainSlugs83

0

우선, 이유를 위해 특정 값을 지정하지 않는 한 (숫자 값이 다른 곳, 즉 데이터베이스 또는 외부 서비스를 의미 함) 숫자 값을 지정하지 않고 명시 적으로 지정하지 마십시오.

두 번째로, 항상 비 플래그 열거 형의 값이 0 인 항목이 있어야합니다. 해당 요소가 기본값으로 사용됩니다.


0

배열 또는 목록에 대한 인덱스로 인덱스를 사용하는 것과 같은 이유가 있거나 비트 연산에서 사용하는 것과 같은 다른 실제적인 이유가없는 경우 0에서 시작하지 마십시오.

당신은 enum그것을 할 필요가 정확히 어디서부터 시작해야한다. 또한 순차적 일 필요는 없습니다. 값이 명시 적으로 설정되면 의미 적 의미 나 실제 고려 사항을 반영해야합니다. 예를 들어, enum"벽의 병"은 1에서 99까지 번호를 매기는 반면 enum4의 거듭 제곱은 4에서 시작하여 16, 64, 256 등으로 계속해야합니다.

또한 값이 0 인 요소를에 추가하는 enum것은 유효한 상태를 나타내는 경우에만 수행해야합니다. 때때로 "없음", "알 수 없음", "누락"등은 유효한 값이지만 여러 번 유효하지 않습니다.


-1

열거 형을 0에서 시작하는 것이 좋습니다. 기본값이므로 알 수없는 값을 -1 값으로 포함하고 싶습니다. 그러면 이것이 기본값이되고 때로는 디버깅에 도움이 될 수 있습니다.


4
끔찍한 생각. 값 형식으로 열거 형은 항상 0으로 초기화됩니다. 알 수 없거나 초기화되지 않은 값을 가지려면 0이어야합니다. 기본값을 -1로 변경할 수 없으며 CLR 전체에서 제로 충전을 하드 코딩합니다.
벤 Voigt

아, 나는 그것을 몰랐다. 일반적으로 데칼 / 초기화 할 때 열거 형 값 / 속성의 값을 설정합니다. 포인터 주셔서 감사합니다.
Tomas McGuinness
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.