SO 게시물을 읽었으며 가장 기본적인 작업이 누락 된 것 같습니다.
public enum LoggingLevel
{
Off = 0,
Error = 1,
Warning = 2,
Info = 3,
Debug = 4,
Trace = 5
};
if (s == "LogLevel")
{
_log.LogLevel = (LoggingLevel)Convert.ToInt32("78");
_log.LogLevel = (LoggingLevel)Enum.Parse(typeof(LoggingLevel), "78");
_log.WriteDebug(_log.LogLevel.ToString());
}
예외가 발생하지 않으므로 기꺼이 보관하십시오 78
. 열거 형에 들어가는 값을 확인하는 방법이 있습니까?
답변
열거 형을 확인하십시오.
용법:
if(Enum.IsDefined(typeof(MyEnum), value))
MyEnum a = (MyEnum)value;
다음은 해당 페이지의 예입니다.
using System;
[Flags] public enum PetType
{
None = 0, Dog = 1, Cat = 2, Rodent = 4, Bird = 8, Reptile = 16, Other = 32
};
public class Example
{
public static void Main()
{
object value;
// Call IsDefined with underlying integral value of member.
value = 1;
Console.WriteLine("{0}: {1}", value, Enum.IsDefined(typeof(PetType), value));
// Call IsDefined with invalid underlying integral value.
value = 64;
Console.WriteLine("{0}: {1}", value, Enum.IsDefined(typeof(PetType), value));
// Call IsDefined with string containing member name.
value = "Rodent";
Console.WriteLine("{0}: {1}", value, Enum.IsDefined(typeof(PetType), value));
// Call IsDefined with a variable of type PetType.
value = PetType.Dog;
Console.WriteLine("{0}: {1}", value, Enum.IsDefined(typeof(PetType), value));
value = PetType.Dog | PetType.Cat;
Console.WriteLine("{0}: {1}", value, Enum.IsDefined(typeof(PetType), value));
// Call IsDefined with uppercase member name.
value = "None";
Console.WriteLine("{0}: {1}", value, Enum.IsDefined(typeof(PetType), value));
value = "NONE";
Console.WriteLine("{0}: {1}", value, Enum.IsDefined(typeof(PetType), value));
// Call IsDefined with combined value
value = PetType.Dog | PetType.Bird;
Console.WriteLine("{0:D}: {1}", value, Enum.IsDefined(typeof(PetType), value));
value = value.ToString();
Console.WriteLine("{0:D}: {1}", value, Enum.IsDefined(typeof(PetType), value));
}
}
예제는 다음 출력을 표시합니다.
// 1: True
// 64: False
// Rodent: True
// Dog: True
// Dog, Cat: False
// None: True
// NONE: False
// 9: False
// Dog, Bird: False
답변
위의 솔루션은 [Flags]
상황을 처리하지 않습니다 .
아래의 솔루션에는 성능 문제가있을 수 있지만 (다양한 방법으로 최적화 할 수 있다고 확신합니다) 본질적으로 열거 형 값이 유효한지 여부를 항상 증명합니다 .
세 가지 가정에 의존합니다.
- C #에서 열거 값은 할 수 없습니다
int
다른 절대적으로 아무것도, - C #의 열거 형 이름 은 알파벳 문자로 시작 해야 합니다
- 빼기 부호와 함께 유효한 열거 이름을 사용할 수 없습니다.
-
ToString()
열거 형을 호출 하면 열거 int
형 (플래그 여부)이 일치하지 않으면 값이 반환됩니다 . 허용 된 열거 형 값이 일치하면 일치하는 이름이 인쇄됩니다.
그래서:
[Flags]
enum WithFlags
{
First = 1,
Second = 2,
Third = 4,
Fourth = 8
}
((WithFlags)2).ToString() ==> "Second"
((WithFlags)(2 + 4)).ToString() ==> "Second, Third"
((WithFlags)20).ToString() ==> "20"
이 두 가지 규칙을 염두에두고 .NET Framework가 올바르게 작업을 수행하면 유효한 열거 형 ToString()
메서드를 호출 하면 알파벳 문자가 첫 문자로 표시됩니다.
public static bool IsValid<TEnum>(this TEnum enumValue)
where TEnum : struct
{
var firstChar = enumValue.ToString()[0];
return (firstChar < '0' || firstChar > '9') && firstChar != '-';
}
이를 “해킹”이라고 부를 수는 있지만 Microsoft의 자체 구현 Enum
및 C # 표준 에 의존함으로써 잠재적으로 버그가있는 코드 나 검사에 의존하지 않는다는 장점이 있습니다. 성능이 그다지 중요하지 않은 상황에서는 많은 불쾌한 switch
진술이나 다른 점검 사항 이 저장됩니다 !
편집하다
내 원래 구현이 음수 값을 지원하지 않음을 지적한 @ChaseMedallion에게 감사드립니다. 이 문제는 해결되고 테스트되었습니다.
그리고 그것을 테스트하는 테스트 :
[TestClass]
public class EnumExtensionsTests
{
[Flags]
enum WithFlags
{
First = 1,
Second = 2,
Third = 4,
Fourth = 8
}
enum WithoutFlags
{
First = 1,
Second = 22,
Third = 55,
Fourth = 13,
Fifth = 127
}
enum WithoutNumbers
{
First, // 1
Second, // 2
Third, // 3
Fourth // 4
}
enum WithoutFirstNumberAssigned
{
First = 7,
Second, // 8
Third, // 9
Fourth // 10
}
enum WithNagativeNumbers
{
First = -7,
Second = -8,
Third = -9,
Fourth = -10
}
[TestMethod]
public void IsValidEnumTests()
{
Assert.IsTrue(((WithFlags)(1 | 4)).IsValid());
Assert.IsTrue(((WithFlags)(1 | 4)).IsValid());
Assert.IsTrue(((WithFlags)(1 | 4 | 2)).IsValid());
Assert.IsTrue(((WithFlags)(2)).IsValid());
Assert.IsTrue(((WithFlags)(3)).IsValid());
Assert.IsTrue(((WithFlags)(1 + 2 + 4 + 8)).IsValid());
Assert.IsFalse(((WithFlags)(16)).IsValid());
Assert.IsFalse(((WithFlags)(17)).IsValid());
Assert.IsFalse(((WithFlags)(18)).IsValid());
Assert.IsFalse(((WithFlags)(0)).IsValid());
Assert.IsTrue(((WithoutFlags)1).IsValid());
Assert.IsTrue(((WithoutFlags)22).IsValid());
Assert.IsTrue(((WithoutFlags)(53 | 6)).IsValid()); // Will end up being Third
Assert.IsTrue(((WithoutFlags)(22 | 25 | 99)).IsValid()); // Will end up being Fifth
Assert.IsTrue(((WithoutFlags)55).IsValid());
Assert.IsTrue(((WithoutFlags)127).IsValid());
Assert.IsFalse(((WithoutFlags)48).IsValid());
Assert.IsFalse(((WithoutFlags)50).IsValid());
Assert.IsFalse(((WithoutFlags)(1 | 22)).IsValid());
Assert.IsFalse(((WithoutFlags)(9 | 27 | 4)).IsValid());
Assert.IsTrue(((WithoutNumbers)0).IsValid());
Assert.IsTrue(((WithoutNumbers)1).IsValid());
Assert.IsTrue(((WithoutNumbers)2).IsValid());
Assert.IsTrue(((WithoutNumbers)3).IsValid());
Assert.IsTrue(((WithoutNumbers)(1 | 2)).IsValid()); // Will end up being Third
Assert.IsTrue(((WithoutNumbers)(1 + 2)).IsValid()); // Will end up being Third
Assert.IsFalse(((WithoutNumbers)4).IsValid());
Assert.IsFalse(((WithoutNumbers)5).IsValid());
Assert.IsFalse(((WithoutNumbers)25).IsValid());
Assert.IsFalse(((WithoutNumbers)(1 + 2 + 3)).IsValid());
Assert.IsTrue(((WithoutFirstNumberAssigned)7).IsValid());
Assert.IsTrue(((WithoutFirstNumberAssigned)8).IsValid());
Assert.IsTrue(((WithoutFirstNumberAssigned)9).IsValid());
Assert.IsTrue(((WithoutFirstNumberAssigned)10).IsValid());
Assert.IsFalse(((WithoutFirstNumberAssigned)11).IsValid());
Assert.IsFalse(((WithoutFirstNumberAssigned)6).IsValid());
Assert.IsFalse(((WithoutFirstNumberAssigned)(7 | 9)).IsValid());
Assert.IsFalse(((WithoutFirstNumberAssigned)(8 + 10)).IsValid());
Assert.IsTrue(((WithNagativeNumbers)(-7)).IsValid());
Assert.IsTrue(((WithNagativeNumbers)(-8)).IsValid());
Assert.IsTrue(((WithNagativeNumbers)(-9)).IsValid());
Assert.IsTrue(((WithNagativeNumbers)(-10)).IsValid());
Assert.IsFalse(((WithNagativeNumbers)(-11)).IsValid());
Assert.IsFalse(((WithNagativeNumbers)(7)).IsValid());
Assert.IsFalse(((WithNagativeNumbers)(8)).IsValid());
}
}
답변
정식 답변은 Enum.IsDefined
이지만 a : 타이트 루프에서 사용하면 약간 느리고 b : [Flags]
열거 형 에는 유용하지 않습니다 .
개인적으로 나는 그것에 대해 걱정하지 않고 switch
적절하게 기억합니다.
- 모든 것을 인식하지 못하고 (아무것도하지 않으면) 괜찮 으면 추가하지 마십시오
default:
(또는default:
이유를 설명 하지 않는 빈 내용이 있음) - 합리적인 기본 행동이 있다면,
default:
- 그렇지 않으면 알고있는 것을 처리하고 나머지는 예외로 처리하십시오.
이렇게 :
switch(someflag) {
case TriBool.Yes:
DoSomething();
break;
case TriBool.No:
DoSomethingElse();
break;
case TriBool.FileNotFound:
DoSomethingOther();
break;
default:
throw new ArgumentOutOfRangeException("someflag");
}
답변
사용하다:
Enum.IsDefined ( typeof ( Enum ), EnumValue );
답변
Enum.IsDefined 사용하십시오 .
답변
에 대처하기 위해 [Flags]
또한 사용 할 수 있습니다 C # 요리 책에서이 솔루션을 :
먼저 ALL
열거 형에 새 값을 추가 하십시오.
[Flags]
enum Language
{
CSharp = 1, VBNET = 2, VB6 = 4,
All = (CSharp | VBNET | VB6)
}
그런 다음 값이 다음에 있는지 확인하십시오 ALL
.
public bool HandleFlagsEnum(Language language)
{
if ((language & Language.All) == language)
{
return (true);
}
else
{
return (false);
}
}
답변
한 가지 방법은 캐스팅과 열거 형을 문자열로 변환하는 것입니다. int를 Enum 유형으로 캐스팅 할 때 int는 해당 enum 값으로 변환되거나 열거 형 값이 int에 대해 정의되지 않은 경우 결과 enum에 int가 값으로 포함됩니다.
enum NetworkStatus{
Unknown=0,
Active,
Slow
}
int statusCode=2;
NetworkStatus netStatus = (NetworkStatus) statusCode;
bool isDefined = netStatus.ToString() != statusCode.ToString();
에지 케이스에 대해서는 테스트되지 않았습니다.