2017-01-03 5 views
3

내 앱에서 알림을 위해 여러 개의 열거 형을 만들었습니다. 각 열거 형은 모듈에 연결됩니다. 단일 열거 형을 사용하면 너무 커질 것이므로이 방법을 사용했습니다. 따라서 module1NotificationTypes, module2NotificationTypes 등여러 열거 형 또는 일반 열거 형

알림 유형을 수신 할 단일 알림 방법을 원합니다. 해당 모듈 열거 형으로 변환 할 수있는 단일 일반 열거 형 값을받는 방법이 있습니까?

public void sendNotification(GenericEnum notificationType) 
{ 
    // Try to convert the generic enum to module1Notification or module2Notification 
} 

또는 여러 개의 열거 형 값을 예상하고 사용하지 않는 값을 "정의되지 않음"으로 설정하여 건너 뛸 수 있도록해야합니까?

public void sendNotification(module1NotificationTypes mod1, module2NotificationTypes mod2) 
{ 
    if(mod1 != Module1Notifications.Undefined) 
    { 
     // We know we received module 1 notification request 
    } 
    else if(mod2 != Module2Notifications.Undefined) 
    { 
     // We know we received module 2 notification request 
    } 
} 
+1

과부하가 발생하는 부분입니다. 열거 형마다 하나의 메소드 만 있으면됩니다. 그것은 외부에서 하나의 방법처럼 보입니다. – Blorgbeard

답변

1

왜 분할 열거를 나는 아래 그 코드의 조각을 포함했다? 열거 형의 이점을 잃어 가고 있습니다.

public void sendNotification(NotificationEnum notificationType) 
{ 
    switch(notificationType) 
    { 
     case NotificationEnum.module_1: 
      // We know we received module 1 notification request 
     break; 
     case NotificationEnum.module_2: 
      // We know we received module 2 notification request 
     break; 
    } 
} 

여러 유형을 동시에 사용할 수있는 경우 [플래그]를 사용하여 열거 형을 표시 할 수 있습니다.

각 열거 형 값을 일부 함수에 매핑하기 위해 사전을 사용하여 곧 내 대답을 업데이트 할 수 있습니다.

이렇게 열거 형을 정의 할 수 있습니다. 기본적으로 최대 값은 32입니다. ulong을 사용하는 경우 최대 값은 64입니다.

[Flags] 
public enum NotificationEnum : ulong 
{ 
    module_1 = 1<<0, 
    module_2 = 1<<1, 
    module_3 = 1<<2, 
    // and so on 
} 

다음을 사용하여 플래그가 지정된 enum을 통해 열거하고 모든 플래그를 가져옵니다.

public static class Enumerations 
{ 
    public static IEnumerable<Enum> GetAllFlags(this Enum values) 
    { 
     foreach (Enum value in Enum.GetValues(values.GetType())) 
     { 
      if (values.HasFlag(value)) 
      { 
       yield return value; 
      } 
     } 
    } 
} 

이제 작업 열거 형 사전을 만듭니다.

Dictionary<NotificationEnum, Action> Actions = new Dictionary<NotificationEnum, Action>() 
{ 
    { NotificationEnum.module_1,() => 
     { 
      // We know we received module 1 notification request 
     } 
    }, 
    { NotificationEnum.module_2,() => 
     { 
      // We know we received module 2 notification request 
     } 
    }, 
    // and so on 
}; 

최종 방법은 간단합니다.

public void sendNotification(NotificationEnum notificationType) 
{ 
    foreach(var action in notificationType.GetAllFlags()) 
    { 
     action(); 
    } 
} 
+0

원래 게시물에서 언급했듯이 하나의 enum이 너무 길어질 것입니다. 항목이 너무 많아서 관리하기 어렵습니다. 귀하의 솔루션이 작동하지 않습니다. 이런 식으로 생각했지만이 솔루션에서는 실제 열거 형을받지 못했습니다. 예 : module1NotificationTypes.DoSomething. enum 유형 NOT notificationType 만 보내고 있습니다. – Sam

+0

@Sam 업데이트를 참조하십시오. 또한 Action 대신에'Action '또는'Func '또는 다른 유형의 델리게이트를 사용할 수 있습니다. 매우 유연합니다. 당신은 여전히 ​​다른 모듈에 대해 서로 다른 사전을 사용할 수 있으며 여러 개의 enum을 가질 수 있습니다. –

+1

이것은 [Cyclomatic Complexity] (https://en.wikipedia.org/wiki/Cyclomatic_complexity)를 줄이기 때문에 정말 좋은 해결책입니다. –

1

생각하고있는 것처럼 열거 형을 열거 할 방법이 없다고 생각합니다. MSDN의이 게시물은 아마도 시나리오를 처리하는 가장 간단한 방법 일 것입니다. 자세한 내용은 다음 link을 방문하십시오.

EDIT 1 링크에 주어진

예는 열거 된 값을 얻기 위해 두 열거 타입 (알파 및 베타) 및 하나의 방법을 갖는다.

열거 :

public enum Alpha { One, Two, Three } 
public enum Beta { Four, Five, Six } 

액세서 방법 :

public T GetOne<T>(object o){ 
    T one = (T)Enum.Parse(typeof(T), o.ToString()); 
    return one; 
} 

방법 사용 :

MessageBox.Show(GetOne<Alpha>(Alpha.One).ToString()); 
+1

게시물에 설명 된 내용을 설명해 주시겠습니까? 게시물을 삭제할 수 있기 때문에 사용자를 게시물로 리디렉션하는 것은 나쁜 습관입니다! – kat1330

0

당신은

public void sendNotification(module1NotificationTypes mod) 
{ 
    //handle notification type 
} 

public void sendNotification(module2NotificationTypes mod) 
{ 

} 

또한 메소드의 오버로드 기술을 사용할 수 있습니다, 당신은

enum module1NotificationTypes 
{ 
    Type1Test1 = 1, 
    Type1Test2 = 2, 
    ... 
} 

enum module2NotificationTypes 
{ 
    Type2Test1 = 101, 
    Type2Test2 = 102, 
} 

다음 int 또는 다른를 받아들이는 방법을 만들 일부 더러운 해킹 및 분할 열거 형 '값의 범위를 할 수 열거 형이 사용하는 정수형 (모든 열거 형은 컴파일 될 때 숫자이기 때문에). 그러나 단순히 오버로드 된 메서드보다 느릴 수 있습니다. 반면 컴파일러는 이러한 동작을 최적화 할 수 있으며 변환을 수행하지 않습니다.

public void sendNotification(int typeNum){ 
    if (typeNum <= 100) 
    { 
     if (!Emum.IsDefined(typeof(module1NotificationTypes), typeNum)) 
     { 
     throw new ArgumentException(); 
     } 
     //DO Processing 
    } 
    else 
    { 
     if (!Emum.IsDefined(typeof(module2NotificationTypes), typeNum)) 
     { 
     throw new ArgumentException(); 
     } 
     //DO Processing 
    } 
} 
1

는 일반적인 열거 형처럼 아무것도 없다,하지만 당신은 (아무것도가 Int32입니다 지정되지 않은 경우) 열거 형은 정수 형의 상단에 있다는 사실을 사용할 수 있습니다. 따라서 기본 유형으로 쉽게 변환 할 수 있습니다. 유형을 공유하면 쉽게 서로 변환 할 수 있습니다.

sendNotification 메서드는 공유 열거 형 집합이 없으면별로 의미가 없습니다. 당신은 (충돌을 방지하기 위해 아마도 명시적인 값) 열거에서 그들을 정의 할 수 있습니다 : 당신이 당신의 모듈 열거를 정의 할 때

public enum NotificationShared { 
    Undefined = 0 
} 

는, 당신이 참조 할 수 있습니다 : 다시

public enum module1Notification { 
    Undefined = NotificationShared.Undefined 
} 

public enum module2Notification { 
    Undefined = NotificationShared.Undefined 
} 

를, 더는 없다 이러한 열거 형을 처리하기위한 일반적인 방법이지만 이제는 최소한 공통 값을 가지므로 변환은 이라는 의미 상 같은 값을 보장합니다.

public void sendNotification<T>(T notificationType) where T : struct 
{ 
    // Convert to shared enum type 
    NotificationShared notification = (NotificationShared)notificationType; 
} 

참으로 조금 못생긴 당신이 때문에 : 당신은 단지 하나의 방법에 대해 가고 싶은 경우 값 형식 제약 조건과 일반적인 방법을 사용하는 경우, 당신은 단지, object 매개 변수와 함께 권투를 피할 수 있습니다 여기서 유형 안전하지 않으며 정적 유형 검사를하지 않습니다. 반면에이 솔루션은 파생 된 열거 형에 종속성을 도입하지 않으므로 커플 링을 줄이고 NotificationShared과 같은 어셈블리에서 구현할 수 있다는 이점이 있습니다. 해당 솔루션의 단점을 피하려면

는 오버로드 코드 중복을 피하기 위해 최선의 선택입니다 : 모든 최적화되지 수 있지만,이 상황을 처리하는 가장 좋은 방법이 될 것입니다 수

public void sendNotification(NotificationShared notificationType) 
{ 
    // Use shared enum type 
} 

public void sendNotification(module1Notification notificationType) 
{ 
    sendNotification((NotificationShared)notificationType); 
} 

public void sendNotification(module2Notification notificationType) 
{ 
    sendNotification((NotificationShared)notificationType); 
} 

.