C #에서 여러 열거 형 값을 어떻게 전달합니까?


117

때때로 다른 사람의 C # 코드를 읽을 때 단일 매개 변수에 여러 열거 형 값을 허용하는 메서드가 표시됩니다. 나는 항상 그것이 깔끔하다고 생각했지만 결코 들여다 보지 못했습니다.

글쎄, 이제 나는 그것을 필요로 할 수도 있지만 방법을 모르겠다.

  1. 이것을 받아들이도록 메소드 서명을 설정하십시오.
  2. 메서드의 값으로 작업
  3. 열거 형 정의

이런 일을 달성하기 위해.


내 특정 상황에서는 다음과 같이 정의 된 System.DayOfWeek를 사용하고 싶습니다.

[Serializable]
[ComVisible(true)]
public enum DayOfWeek
{ 
    Sunday = 0,   
    Monday = 1,   
    Tuesday = 2,   
    Wednesday = 3,   
    Thursday = 4,   
    Friday = 5,    
    Saturday = 6
}

하나 이상의 DayOfWeek 값을 메서드에 전달할 수 있기를 원합니다. 이 특정 열거 형을 그대로 사용할 수 있습니까? 위에 나열된 3 가지를 어떻게하나요?


1
아래에서 언급했듯이 Flags 열거 형을 사용할 수 있습니다. Flags 열거 형 작업에 대한 자세한 정보가 포함 된 C # 열거 형의 내부 및 외부를 확인할 수 있습니다 .
ChaseMedallion 2014

답변:


181

열거 형을 정의 할 때 [Flags]로 속성을 지정하고 값을 2의 거듭 제곱으로 설정하면 이러한 방식으로 작동합니다.

함수에 여러 값을 전달하는 것 외에 다른 변경 사항은 없습니다.

예를 들면 :

[Flags]
enum DaysOfWeek
{
   Sunday = 1,
   Monday = 2,
   Tuesday = 4,
   Wednesday = 8,
   Thursday = 16,
   Friday = 32,
   Saturday = 64
}

public void RunOnDays(DaysOfWeek days)
{
   bool isTuesdaySet = (days & DaysOfWeek.Tuesday) == DaysOfWeek.Tuesday;

   if (isTuesdaySet)
      //...
   // Do your work here..
}

public void CallMethodWithTuesdayAndThursday()
{
    this.RunOnDays(DaysOfWeek.Tuesday | DaysOfWeek.Thursday);
}

자세한 내용 은 열거 형 유형에 대한 MSDN 설명서를 참조하십시오 .


질문 추가에 대한 응답으로 수정합니다.

배열 / 컬렉션 / 매개 변수 배열로 전달하는 것과 같은 작업을 원하지 않는 한 해당 열거 형을 그대로 사용할 수 없습니다. 그러면 여러 값을 전달할 수 있습니다. flags 구문에서는 Enum을 플래그로 지정해야합니다 (또는 설계되지 않은 방식으로 언어를 엉망으로 만들기 위해).


9
이것이 작동하기를 원한다면 값은 각 값에 대해 단일 비트 인 2의 거듭 제곱으로 정의되어야한다고 생각합니다. 매개 변수 값의 비트 OR을 전달하면 비트 AND 연산을 사용하여 확인할 수 있습니다. 예를 들어, 1,2,4,8 등과 같이 값을 정의하지 않으면 문제가 발생합니다.
Denis Troller

1
Flags 속성 만 설정하면 자동으로 작동하지 않습니다. 나는 그것을 시도했다.
Richard Anthony Hein

1
당신 말이 맞고 잘못된 정보를 제거했습니다. 리드의 코드도 수정했습니다.
Matthew Scharley

@monoxide : 동시에 수정했습니다. 수정 사항을 덮어 쓰게되어 죄송합니다.
Reed Copsey 2009-06-23

2
문제 없습니다 ... 저는 여전히 그런 플래그 값에 16 진수를 사용하는 것을 선호합니다. 나에게는 더 명확 해 보이지만 각각은 자신의 것입니다.
Matthew Scharley 2009-06-23

78

더 우아한 해결책은 HasFlag ()를 사용하는 것입니다.

    [Flags]
    public enum DaysOfWeek
    {
        Sunday = 1,
        Monday = 2,
        Tuesday = 4,
        Wednesday = 8,
        Thursday = 16,
        Friday = 32,
        Saturday = 64
    }

    public void RunOnDays(DaysOfWeek days)
    {
        bool isTuesdaySet = days.HasFlag(DaysOfWeek.Tuesday);

        if (isTuesdaySet)
        {
            //...
        }
    }

    public void CallMethodWithTuesdayAndThursday()
    {
        RunOnDays(DaysOfWeek.Tuesday | DaysOfWeek.Thursday);
    }

이 방법을 사용하면 알아야 할 또 다른 중요한 사항이 있습니다. 열거 형을 동적으로 채워야 할 때 훨씬 더 많은 유연성을 추가합니다. 예 : 체크 박스를 사용하여 프로그램을 실행할 요일을 정의하고 위에서 수행 한 방식으로이를 수행하려고하면 코드를 읽을 수 없습니다. 따라서 대신 다음과 같이 할 수 있습니다. ... DaysOfWeek days = new DaysOfWeek(); if (cbTuesday.Checked) days |= DaysOfWeek.Tuesday; if (cbWednesday.Checked) days |= DaysOfWeek.Wednesday;...
CoastN

25

두 번째 리드의 대답입니다. 그러나 열거 형을 만들 때 일종의 비트 필드를 만들 수 있도록 각 열거 형 멤버에 대한 값을 지정해야합니다. 예를 들면 :

[Flags]
public enum DaysOfWeek
{
    Sunday = 1,
    Monday = 2,
    Tuesday = 4,
    Wednesday = 8,
    Thursday = 16,
    Friday = 32,
    Saturday = 64,

    None = 0,
    All = Weekdays | Weekend,
    Weekdays = Monday | Tuesday | Wednesday | Thursday | Friday,
    Weekend = Sunday | Saturday,
    // etc.
}

1
예를 들어 데이터베이스에 저장된 값을 읽는 경우와 같이 DaysOfWeek 값을 검사해야하는 경우 도움이됩니다. 또한 일부 프로그래머는 일요일이 아닌 월요일부터 요일을 열거하므로 다른 프로그래머에게 더 나은 문서를 제공합니다.
Jacob

3
명확성과 유지 보수성을 위해 'All'열거 형을 "Sunday | Monday | Tuesday | Wednesday | Thursday | Friday | Saturday"...로 쓰고 '주중'과 '주말'에 유사한 표기법을 사용합니다.
Robert Cartaino

당신이 당신의 자신의 열거를 만들 수 있지만, 기존 DaysOfWeek 열거 변경할 수 없습니다 질문에 대답하려는 경우 괜찮
로버트 폴슨

2
"하고 싶을 수도"가 아니라 ... 당신은 반드시해야합니다. 비트 비교에는 필요합니다. 값을 지정하지 않으면 작동하지 않습니다.
Richard Anthony Hein

11

내 특정 상황에서는 System.DayOfWeek를 사용하고 싶습니다.

System.DayOfWeek를 [Flags]제어 할 수 없기 때문에 열거 형 으로 사용할 수 없습니다 . 다중 DayOfWeek을 받아들이는 방법을 원한다면 params키워드 를 사용해야합니다.

void SetDays(params DayOfWeek[] daysToSet)
{
    if (daysToSet == null || !daysToSet.Any())
        throw new ArgumentNullException("daysToSet");

    foreach (DayOfWeek day in daysToSet)
    {
        // if( day == DayOfWeek.Monday ) etc ....
    }
}

SetDays( DayOfWeek.Monday, DayOfWeek.Sunday );

그렇지 않으면 [Flags]수많은 다른 응답자에 의해 설명 된대로 고유 한 열거를 만들고 비트 비교를 사용할 수 있습니다.


2
왜 내가 params를 생각하지 않았는지 모르겠습니다. 비트 필드가 아닌 열거 형을 사용하는 데 매우 유용합니다.
Ronnie Overby 2009-06-23

10
[Flags]
public enum DaysOfWeek
{
  Mon = 1,
  Tue = 2,
  Wed = 4,
  Thur = 8,
  Fri = 16,
  Sat = 32,
  Sun = 64
}

숫자를 지정하고 비트 방식으로 값을 저장하기 때문에 이렇게 증가시켜야합니다.

그런 다음이 열거 형을 취하는 방법을 정의하십시오.

public void DoSomething(DaysOfWeek day)
{
  ...
}

그리고 그것을 호출하려면 다음과 같이하십시오.

DoSomething(DaysOfWeek.Mon | DaysOfWeek.Tue) // Both Monday and Tuesday

열거 형 값 중 하나가 포함되었는지 확인하려면 다음과 같은 비트 연산을 사용하여 확인하십시오.

public void DoSomething(DaysOfWeek day)
{
  if ((day & DaysOfWeek.Mon) == DaysOfWeek.Mon) // Does a bitwise and then compares it to Mondays enum value
  {
    // Monday was passed in
  }
}

질문에 대답하지 않습니다. "내 특정 상황에서, 나는 System.DayOfWeek 사용하고 싶습니다"
로버트 폴슨

그러나 그것은 정확히 내가 찾고 있던 것입니다. 어쨌든 감사합니다.
Tillito 2011 년

3
[Flags]
    public enum DaysOfWeek{


        Sunday = 1 << 0,
        Monday = 1 << 1,
        Tuesday = 1 << 2,
        Wednesday = 1 << 3,
        Thursday = 1 << 4,
        Friday =  1 << 5,
        Saturday =  1 << 6
    }

이 형식으로 메서드 호출

MethodName (DaysOfWeek.Tuesday | DaysOfWeek.Thursday);

EnumToArray 메서드를 구현하여 옵션 전달

private static void AddEntryToList(DaysOfWeek days, DaysOfWeek match, List<string> dayList, string entryText) {
            if ((days& match) != 0) {
                dayList.Add(entryText);
            }
        }

        internal static string[] EnumToArray(DaysOfWeek days) {
            List<string> verbList = new List<string>();

            AddEntryToList(days, HttpVerbs.Sunday, dayList, "Sunday");
            AddEntryToList(days, HttpVerbs.Monday , dayList, "Monday ");
            ...

            return dayList.ToArray();
        }

질문에 대답하지 않습니다. "내 특정 상황에서, 나는 System.DayOfWeek 사용하고 싶습니다"
로버트 폴슨

고마워요, 로버트.하지만 모든 답변에서이 점을 지적 할 필요는 없습니다.
Ronnie Overby 2009-06-23

@Ronnie-실제로 질문에 답변하지 않은 거의 중복 된 답변이 너무 많아서 제 잘못은 거의 없습니다.
Robert Paulson

@Rony-열거 형 ToString () 및 Enum.Parse ()는 [Flags] 열거를 올바르게 출력 / 파싱합니다 (물론 열거 버전 관리에주의하는 한)
Robert Paulson

@Robert-나는 아무도 당신을 비난하고 있다고 생각하지 않습니다. 투표로 말을하게하십시오.
Ronnie Overby 2009-06-23

3

[Flags] 속성으로 열거 형을 표시하십시오. 또한 모든 값이 1,2,4,8,16,32,64와 같이 상호 배타적인지 확인하십시오 (두 값이 서로 같을 수 없음).

[Flags]
public enum DayOfWeek
{ 
Sunday = 1,   
Monday = 2,   
Tuesday = 4,   
Wednesday = 8,   
Thursday = 16,   
Friday = 32,    
Saturday = 64
}

DayOfWeek 열거 형을 허용하는 메서드가있는 경우 비트 또는 연산자 (|)를 사용하여 여러 멤버를 함께 사용합니다. 예를 들면 :

MyMethod(DayOfWeek.Sunday|DayOfWeek.Tuesday|DayOfWeek.Friday)

매개 변수에 특정 멤버가 포함되어 있는지 확인하려면 확인중인 멤버에 비트 연산자 (&)를 사용하십시오.

if(arg & DayOfWeek.Sunday == DayOfWeek.Sunday)
Console.WriteLine("Contains Sunday");

질문에 대답하지 않습니다. "내 특정 상황에서, 나는 System.DayOfWeek 사용하고 싶습니다"
로버트 폴슨

2

Reed Copsey가 정확하고 가능하면 원본 게시물에 추가 할 수 있지만 답장을 보내야합니다.

이전 열거 형에 [Flags]를 사용하는 것은 위험합니다. 값의 충돌을 피하기 위해 플래그를 사용할 때 열거 형 값을 2의 거듭 제곱으로 명시 적으로 변경해야한다고 생각합니다. FlagsAttribute 및 Enum 지침을 참조하십시오 .



-3

이러한 성격의 무언가는 당신이 찾고있는 것을 보여 주어야합니다 :

[Flags]
public enum SomeName
{
    Name1,
    Name2
}

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