2014-06-11 2 views
5

|&enum 등은 사용할 수 있지만 Enum은 사용할 수 없습니다. 왜 이런거야? 이 주위에 어떤 방법이 있습니까? WPF에 대한 Enum 플래그 변환기를 쓰려고합니다. 왜 이런 일이연산자 '|' 'System.Enum'및 'System.Enum'유형의 피연산자에 적용 할 수 없습니다

public class EnumFlagConverter : IValueConverter 
{ 
    public Enum CurrentValue; 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     var theEnum = value as Enum; 
     CurrentValue = theEnum; 
     return theEnum.HasFlag(parameter as Enum); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     Enum CurrentValue; 
     var theEnum = parameter as Enum; 
     if (CurrentValue.HasFlag(theEnum)) //this line is allowed 
      return CurrentValue &= ~theEnum; //~theEnum not allowed, neither is the &= 
     else 
      return CurrentValue |= theEnum; // |= cannot be applied to Enum and Enum 
    } 
} 
+0

당신이 같은 유형을 지정할 수'int' 대신에, 그리고에 암시 적 변환 'Enum' 작동 희망? – Matthew

+2

"Enum은 정의 된 작업이없는 클래스이므로"나는 혼란을 이해하는 데 어려움을 겪고 있다고 생각합니다. 그것은 문자열 foo | = "bar"를 사용할 수없는 것과 같은 이유입니다 –

+0

"Enum"(실제로는 System.Enum)이 유형이고 "enum"은 유형을 선언하는 데 사용되는 키워드라는 것을 이해하는 것이 도움이 될 수 있습니다 유형. –

답변

7

입니까? 컴파일러는 열거의 기본 유형을 알고있는 경우

컴파일러는 문제없이 비트 연산을 수행 할 수 있습니다. 컴파일러가 기본 유형을 모르는 경우에는 8 비트, 16 비트, 32 비트 또는 64 비트 연산 중 원하는 것을 알 수없고 완전히 포기합니다. 컴파일러는 두 열거 형 값 중 어느 것도 null이 아니며 컴파일러에서 두 열거 형 값이 동일한 유형 또는 너비를 가졌다는 것을 알 수있는 방법이 없다는 점에 유의하십시오.

이 방법이 있습니까?

64 비트보다 큰 열거 형을 다루지 않으며 64 비트 연산은 8 비트 열거 형의 경우에도 올바른 결과를 생성한다는 것을 알 수 있습니다. 따라서 작업을 명시 적으로 64 비트 연산으로 작성하여 컴파일러를 지원할 수 있습니다.

static Enum Or(Enum a, Enum b) 
{ 
    // consider adding argument validation here 

    if (Enum.GetUnderlyingType(a.GetType()) != typeof(ulong)) 
     return (Enum)Enum.ToObject(a.GetType(), Convert.ToInt64(a) | Convert.ToInt64(b)); 
    else 
     return (Enum)Enum.ToObject(a.GetType(), Convert.ToUInt64(a) | Convert.ToUInt64(b)); 
} 

And에 대해서도 마찬가지이다.

+0

완벽! 열거 형 객체를 Enum으로 바꾸는 방법이 있다는 것을 알았지 만 ToObject 메소드에 대해서는 알지 못했습니다. 감사! – DLeh

0

허용 된 대답을 사용하여이 변환기를 사용하여 여러 개의 확인란을 [Flags]Enum에 바인딩했습니다. 참고 :이 변환기는 클래스 멤버를 사용하므로 여러 바인딩 집합에 대해 동일한 변환기 인스턴스를 다시 사용하지 마십시오.

XAML :

<StackPanel> 
    <StackPanel.Resources> 
     <local:EnumFlagConverter x:Key="myConverter" /> 
    </StackPanel.Resources> 
    <CheckBox Content="Option1" IsChecked="{Binding TheEnum, Converter={StaticResource myConverter}, ConverterParameter={x:Static local:MyEnum.Option1}}" /> 
    <CheckBox Content="Option2" IsChecked="{Binding TheEnum, Converter={StaticResource myConverter}, ConverterParameter={x:Static local:MyEnum.Option2}}" /> 
    <CheckBox Content="Option3" IsChecked="{Binding TheEnum, Converter={StaticResource myConverter}, ConverterParameter={x:Static local:MyEnum.Option3}}" /> 
</StackPanel> 

C 번호 :

public class EnumFlagConverter : IValueConverter 
{ 
    public Enum CurrentValue { get; set; } 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     var theEnum = value as Enum; 
     CurrentValue = theEnum; 
     return theEnum.HasFlag(parameter as Enum); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     var theEnum = parameter as Enum; 
     if (CurrentValue.HasFlag(theEnum)) 
      CurrentValue = CurrentValue.And(theEnum.Not()); 
     else 
      CurrentValue = CurrentValue.Or(theEnum); 
     return CurrentValue; 
    } 
} 


public static class Extensions 
{ 
    public static Enum Or(this Enum a, Enum b) 
    { 
     // consider adding argument validation here 
     if (Enum.GetUnderlyingType(a.GetType()) != typeof(ulong)) 
      return (Enum)Enum.ToObject(a.GetType(), Convert.ToInt64(a) | Convert.ToInt64(b)); 
     else 
      return (Enum)Enum.ToObject(a.GetType(), Convert.ToUInt64(a) | Convert.ToUInt64(b)); 
    } 

    public static Enum And(this Enum a, Enum b) 
    { 
     // consider adding argument validation here 
     if (Enum.GetUnderlyingType(a.GetType()) != typeof(ulong)) 
      return (Enum)Enum.ToObject(a.GetType(), Convert.ToInt64(a) & Convert.ToInt64(b)); 
     else 
      return (Enum)Enum.ToObject(a.GetType(), Convert.ToUInt64(a) & Convert.ToUInt64(b)); 
    } 
    public static Enum Not(this Enum a) 
    { 
     // consider adding argument validation here 
     return (Enum)Enum.ToObject(a.GetType(), ~Convert.ToInt64(a)); 
    } 
} 
관련 문제