[c#] 누구나 열거 형 제네릭 제약 조건이없는 경우 좋은 해결 방법을 알고 있습니까?

내가 원하는 것은 다음과 같습니다. 플래그가 지정된 값이 결합 된 열거 형이 있습니다.

public static class EnumExtension
{
    public static bool IsSet<T>( this T input, T matchTo ) 
        where T:enum //the constraint I want that doesn't exist in C#3
    {
        return (input & matchTo) != 0;
    }
}

그래서 다음과 같이 할 수 있습니다.

MyEnum tester = MyEnum.FlagA | MyEnum.FlagB

if( tester.IsSet( MyEnum.FlagA ) )
    //act on flag a

불행히도 제약 조건에 열거 형 제한이없고 클래스와 구조체 만있는 C #의 제네릭입니다. C #은 열거 형을 구조체로 보지 않으므로 (값 유형 임에도 불구하고) 이와 같은 확장 유형을 추가 할 수 없습니다.

누구든지 해결 방법을 알고 있습니까?



답변

편집 : 이것은 이제 UnconstrainedMelody의 0.0.0.2 버전에 있습니다.

( enum 제약 조건에 대한블로그 게시물 에서 요청한대로 . 독립형 답변을 위해 아래 기본 사실을 포함했습니다.)

가장 좋은 해결책은 UnconstrainedMelody 1 에 포함시킬 때까지 기다리는 것입니다 . 이것은 다음과 같은 “가짜”제약 조건이있는 C # 코드를 사용하는 라이브러리입니다.

where T : struct, IEnumConstraint

그리고 그것을

where T : struct, System.Enum

빌드 후 단계를 통해.

작성하기가 너무 어렵지 않아야 IsSet합니다. Int64기반 및 UInt64기반 플래그 를 모두 처리 하는 것이 까다로운 부분이 될 수 있지만. (기본적으로 UInt64.

전화를 걸면 어떤 행동을 원하십니까?

tester.IsSet(MyFlags.A | MyFlags.C)

? 지정된 모든 플래그가 설정 되었는지 확인해야합니까 ? 그것이 내 기대입니다.

오늘 밤 집으로가는 길에이 작업을 수행해 보겠습니다. 라이브러리를 사용 가능한 표준에 빠르게 맞추고 잠시 휴식을 취하기 위해 유용한 enum 메서드에 대한 빠른 블리츠를 기대하고 있습니다.

편집하다 : 그건 IsSet그렇고, 이름이 확실하지 않습니다 . 옵션 :

  • 포함
  • 포함
  • HasFlag (또는 HasFlags)
  • IsSet (확실히 옵션 임)

생각을 환영합니다. 어차피 결정이 내려지기까지는 시간이 좀 걸릴 거라고 확신 해요 …


1 또는 패치로 제출하십시오.


답변

C # 7.3부터는 enum 제약 조건을 추가하는 기본 제공 방법이 있습니다.

public class UsingEnum<T> where T : System.Enum { }

출처 : https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/where-generic-type-constraint


답변

Darren, 유형이 특정 열거 형이면 작동합니다. 일반 열거 형이 작동하려면 부울 수학을 수행하기 위해 int (또는 더 가능성이 높은 uint)로 캐스팅해야합니다.

public static bool IsSet( this Enum input, Enum matchTo )
{
    return ( Convert.ToUInt32( input ) & Convert.ToUInt32( matchTo ) ) != 0;
}


답변

사실 추악한 속임수로 가능합니다. 그러나 확장 방법에는 사용할 수 없습니다.

public abstract class Enums<Temp> where Temp : class {
    public static TEnum Parse<TEnum>(string name) where TEnum : struct, Temp {
        return (TEnum)Enum.Parse(typeof(TEnum), name);
    }
}
public abstract class Enums : Enums<Enum> { }

Enums.IsSet<DateTimeKind>("Local")

원하는 경우 as를 사용 Enums<Temp>하여 개인 생성자 및 공용 중첩 추상 상속 클래스를 제공하여 비 열거 형에 대한 상속 된 버전을 방지 할 수 있습니다.TempEnum


답변

IL Weaving 및 ExtraConstraints를 사용하여이를 달성 할 수 있습니다.

이 코드를 작성할 수 있습니다.

public class Sample
{
    public void MethodWithDelegateConstraint<[DelegateConstraint] T> ()
    {
    }
    public void MethodWithEnumConstraint<[EnumConstraint] T>()
    {
    }
}

컴파일되는 항목

public class Sample
{
    public void MethodWithDelegateConstraint<T>() where T: Delegate
    {
    }

    public void MethodWithEnumConstraint<T>() where T: struct, Enum
    {
    }
}


답변

C # 7.3부터는 제네릭 형식에 대해 Enum 제약 조건을 사용할 수 있습니다.

public static TEnum Parse<TEnum>(string value) where TEnum : Enum
{
    return (TEnum) Enum.Parse(typeof(TEnum), value);
}

Nullable 열거 형을 사용하려면 원래 구조체 제약 조건을 그대로 두어야합니다.

public static TEnum? TryParse<TEnum>(string value) where TEnum : struct, Enum
{
    if( Enum.TryParse(value, out TEnum res) )
        return res;
    else
        return null;
}


답변

이것은 원래 질문에 대답하지 않지만 이제 .NET 4에는 Enum.HasFlag 라는 메서드가 있습니다.이 메서드는 예제에서 수행하려는 작업을 수행합니다.