사람들은 왜 항상 열거 값이 좋아 사용 0, 1, 2, 4, 8
하지 0, 1, 2, 3, 4
?
비트 연산 등과 관련이 있습니까?
이것이 올바르게 사용되는 방법에 대한 작은 샘플 스 니펫에 감사드립니다. :)
[Flags]
public enum Permissions
{
None = 0,
Read = 1,
Write = 2,
Delete = 4
}
사람들은 왜 항상 열거 값이 좋아 사용 0, 1, 2, 4, 8
하지 0, 1, 2, 3, 4
?
비트 연산 등과 관련이 있습니까?
이것이 올바르게 사용되는 방법에 대한 작은 샘플 스 니펫에 감사드립니다. :)
[Flags]
public enum Permissions
{
None = 0,
Read = 1,
Write = 2,
Delete = 4
}
답변:
그들은 2의 거듭 제곱이고 나는 이것을 할 수 있기 때문에 :
var permissions = Permissions.Read | Permissions.Write;
아마 나중에 ...
if( (permissions & Permissions.Write) == Permissions.Write )
{
// we have write access
}
비트 필드이며, 각 세트 비트는 일부 권한 (또는 열거 된 값이 논리적으로 일치하는 것)에 해당합니다. 이것이 정의 된 1, 2, 3, ...
경우이 방식으로 비트 연산자를 사용할 수없고 의미있는 결과를 얻을 수 없습니다. 더 깊이 탐구하려면 ...
Permissions.Read == 1 == 00000001
Permissions.Write == 2 == 00000010
Permissions.Delete == 4 == 00000100
여기에 패턴이 있습니까? 이제 원래 예를 들어 보면
var permissions = Permissions.Read | Permissions.Write;
그때...
permissions == 00000011
보다? 모두 Read
와 Write
비트가 설정되고, 그 독립적으로 확인할 수 있습니다합니다 (있음 또한 통지 Delete
비트가되어 있지 설정을하기 때문에이 값은 삭제할 수있는 권한을 전달하지 않습니다).
하나의 비트 필드에 여러 플래그를 저장할 수 있습니다.
myEnum.IsSet
. 나는 이것이 완전히 쓸모없는 추상화이며 타이핑을 줄이는 데만 도움이된다고 생각하지만 meh
Flags
속성은 당신에게 '예쁜 인쇄'iirc를주는 것 이상을 수행하지 않습니다. 속성의 존재 여부에 관계없이 열거 된 값을 플래그로 사용할 수 있습니다.
0
아니다 false
; false
입니다 false
. 그러나 당신은 쓸 수 if((permissions & Permissions.Write) > 0)
있습니다.
(permissions & Permissions.Write) == Permissions.Write
이제 다음을 사용할 수 있습니다.enum.HasFlag()
다른 답변에서 여전히 명확하지 않은 경우 다음과 같이 생각하십시오.
[Flags]
public enum Permissions
{
None = 0,
Read = 1,
Write = 2,
Delete = 4
}
작성하는 더 짧은 방법입니다.
public enum Permissions
{
DeleteNoWriteNoReadNo = 0, // None
DeleteNoWriteNoReadYes = 1, // Read
DeleteNoWriteYesReadNo = 2, // Write
DeleteNoWriteYesReadYes = 3, // Read + Write
DeleteYesWriteNoReadNo = 4, // Delete
DeleteYesWriteNoReadYes = 5, // Read + Delete
DeleteYesWriteYesReadNo = 6, // Write + Delete
DeleteYesWriteYesReadYes = 7, // Read + Write + Delete
}
여덟 가지 가능성이 있지만 네 멤버 만 조합하여 나타낼 수 있습니다. 16 개의 가능성이 있다면 5 명의 조합으로 나타낼 수 있습니다. 40 억 개의 가능성이 있다면 33 명의 조합으로 나타낼 수 있습니다! 열거 형에 40 억 개의 항목을 명명하려고 시도하는 것보다 각각 33의 구성원 (각 0을 제외하고)의 2 제곱을 갖는 것이 훨씬 낫습니다.
enum
40 억 명의 회원 이있는 정신적 이미지 +1 그리고 슬픈 부분은 아마도 누군가가 그것을 시도했을 것입니다.
2 ** -infinity
2의 거듭 제곱으로 계산하지 않는 한 ).
이 값들은 이진수로 고유 한 비트 위치를 나타 내기 때문에 :
1 == binary 00000001
2 == binary 00000010
4 == binary 00000100
등등
1 | 2 == binary 00000011
편집하다:
3 == binary 00000011
이진수로 3은 1과 2의 위치에서 1의 값으로 표시됩니다. 실제로 값과 같습니다 1 | 2
. 따라서 이진 자리를 플래그로 사용하여 일부 상태를 나타내는 경우 3은 의미가 없습니다 (실제로 두 값의 조합 인 논리적 값이없는 한)
더 명확히하기 위해 다음과 같이 예제 열거 형을 확장 할 수 있습니다.
[Flags]
public Enum Permissions
{
None = 0, // Binary 0000000
Read = 1, // Binary 0000001
Write = 2, // Binary 0000010
Delete = 4, // Binary 0000100
All = 7, // Binary 0000111
}
따라서,에는 Permissions.All
또한 암시 적 Permissions.Read
으로 Permissions.Write
, 및Permissions.Delete
3
이다 11
, 즉 바이너리는 의미있는 값으로 임의의 위치에 1 개 비트를지도 할 수있는 능력을 상실하므로,이, 한 세트의 비트에 매핑되지 않습니다.
2|3 == 1|3 == 1|2 == 3
합니다. 당신이 바이너리 값을 가질 경우에 따라서 00000011
, 당신의 플래그 값을 포함 1
, 2
그리고 3
, 당신은 그 값을 나타내는 경우 모르겠다 1 and 3
, 2 and 3
, 1 and 2
또는 only 3
. 그것은 훨씬 덜 유용합니다.
이들은 열거 형 값의 조합을 허용하는 비트 플래그를 나타내는 데 사용됩니다. 16 진수 표기법으로 값을 쓰면 더 명확하다고 생각합니다.
[Flags]
public Enum Permissions
{
None = 0x00,
Read = 0x01,
Write = 0x02,
Delete= 0x04,
Blah1 = 0x08,
Blah2 = 0x10
}
4194304
2 를 곱하면 무엇을 얻 습니까? 어때요 0x400000
? 0x800000
보다 정답 으로 인식 하는 것이 훨씬 쉽고 8388608
16 진수 값을 입력하는 것이 오류가 적습니다.
0x10000
2의 거듭 제곱은? 예, 1, 2, 4 또는 8로 시작하고 그 후에는 모두 0입니다. 당신은 정신적으로 0x10을 16으로 번역 할 필요가 없습니다. (그렇게하면 결국 제 2의 자연이 될 것입니다.) 단지 "일부 2의 힘"으로 생각하십시오.
이것은 실제로 더 많은 주석이지만 형식을 지원하지 않기 때문에 플래그 열거를 설정하는 데 사용한 방법을 포함하고 싶었습니다.
[Flags]
public enum FlagTest
{
None = 0,
Read = 1,
Write = Read * 2,
Delete = Write * 2,
ReadWrite = Read|Write
}
이 접근 방식은 플래그를 알파벳 순서로 유지하려는 경우 개발 중에 특히 유용합니다. 새 플래그 값을 추가해야한다고 결정한 경우 알파벳순으로 삽입 할 수 있으며 변경해야하는 유일한 값은 이전 값입니다.
그러나 솔루션이 프로덕션 시스템에 게시되면 (특히 웹 서비스와 같이 밀접한 결합없이 열거 형이 노출 된 경우) 열거 형 내의 기존 값을 변경하지 않는 것이 좋습니다.
이것에 대한 좋은 답변이 많이 있습니다 ... 그냥 말할 것입니다. 구문이 표현하려고하는 것을 좋아하지 않거나 쉽게 파악할 수없는 경우<<
개인적으로 대안을 선호합니다 (그리고 직접 열거 형 선언 스타일을 감히 말합니다 ) …
typedef NS_OPTIONS(NSUInteger, Align) {
AlignLeft = 00000001,
AlignRight = 00000010,
AlignTop = 00000100,
AlignBottom = 00001000,
AlignTopLeft = 00000101,
AlignTopRight = 00000110,
AlignBottomLeft = 00001001,
AlignBottomRight = 00001010
};
NSLog(@"%ld == %ld", AlignLeft | AlignBottom, AlignBottomLeft);
LOG 513 == 513
이해하기가 훨씬 쉬워졌습니다. 하나를 정렬하십시오… 원하는 결과를 설명하고, 원하는 결과를 얻으십시오. "계산"이 필요하지 않습니다.