Enum에 확장 메서드를 추가하는 방법


122

이 Enum 코드가 있습니다.

enum Duration { Day, Week, Month };

이 Enum에 대한 확장 메서드를 추가 할 수 있습니까?


1
당신은 이것을 본 적 있습니까? stackoverflow.com/questions/2422113/…
badpanda 2013 년


짧은 대답입니다. 이 특정한 경우에 당신은의 사용을 고려하는 것이 좋습니다TimeSpan
Jodrell

1
열거 형에 확장 메서드를 사용하면 더럽게 느껴질 것입니다. 필요한 것을 캡슐화하는 클래스를 만듭니다. 열거 형을 가능한 한 간단하게 유지하십시오. 관련된 로직이 더 필요하면 일, 주, 월을 노출하는 Duration 클래스를 만들고 확장 메서드에 있었던 다른 로직을 포함합니다.
Jason Evans

2
플래그 그룹에 대한 열거 형 확장 메서드를 갖는 것을 좋아합니다. 예를 들어 조항이 경우에 내가 선호하는 Day.IsWorkday()이상 (Day & Days.Workday) > 0Days.Workday같이 정의 Monday | Tuesday ... | Friday. 내 의견으로는 전자가 더 명확하고 후자가 정확히 구현되었습니다.
세바스찬 WERK

답변:


114

사이트 에 따르면 :

확장 메서드는 팀의 다른 사람들이 실제로 발견하고 사용할 수있는 방식으로 기존 클래스에 대한 메서드를 작성하는 방법을 제공합니다. 열거 형이 다른 클래스와 같은 클래스라는 점을 감안할 때 다음과 같이 확장 할 수 있다는 것은 그리 놀라운 일이 아닙니다.

enum Duration { Day, Week, Month };

static class DurationExtensions 
{
  public static DateTime From(this Duration duration, DateTime dateTime) 
  {
    switch (duration) 
    {
      case Day:   return dateTime.AddDays(1);
      case Week:  return dateTime.AddDays(7);
      case Month: return dateTime.AddMonths(1);
      default:    throw new ArgumentOutOfRangeException("duration");
    }
  }
}

일반적으로 열거 형이 최선의 선택은 아니라고 생각하지만 적어도 이것은 스위치 / if 처리 중 일부를 중앙 집중화하고 더 나은 일을 할 수있을 때까지 추상화 할 수 있습니다. 값도 범위 내에 있는지 확인하십시오.

여기 Microsft MSDN에서 자세한 내용을 읽을 수 있습니다 .


나는 "enums are evil"주석이 적절하지 않지만 현실에 근거를 가지고 있다고 믿습니다. 열거 형이 문제가 될 수 있다는 것을 알았습니다. 특정 컨텍스트와 동작에 고정되어 있기 때문입니다.
Ed Schwehm 2013 년

1
이것은 컴파일되고 실행되기 때문에 C #의 열거 형은 짜증나게합니다 :Duration d = 0;
Graham

16
Given that enums are classes아니 그들은 수업이 아닙니다.
Winger Sendon 2017 년

1
요일 및 확장 메서드 IsWeekday (), IsWeekendday ()와 같이 직접 열거 형에 관한 경우에만 이러한 종류의 확장을 사용합니다. 그러나 클래스는 동작을 캡슐화하기위한 것이므로 캡슐화 할 동작이 많거나 복잡한 경우 클래스가 더 좋습니다. 제한적이고 기본적이라면 개인적으로 열거 형에 대한 확장이 괜찮다는 것을 알 수 있습니다. 대부분의 설계 결정과 마찬가지로 선택 사이에 모호한 경계 (IMO)가 있습니다. 확장은 중첩 된 클래스가 아닌 최상위 정적 클래스에서만 수행 할 수 있습니다. 열거 형이 클래스의 일부인 경우 클래스를 만들어야합니다.
FreeText

51

Enum의 인스턴스가 아닌 Enum 유형에 확장 메서드를 추가 할 수도 있습니다.

/// <summary> Enum Extension Methods </summary>
/// <typeparam name="T"> type of Enum </typeparam>
public class Enum<T> where T : struct, IConvertible
{
    public static int Count
    {
        get
        {
            if (!typeof(T).IsEnum)
                throw new ArgumentException("T must be an enumerated type");

            return Enum.GetNames(typeof(T)).Length;
        }
    }
}

다음을 수행하여 위의 확장 메서드를 호출 할 수 있습니다.

var result = Enum<Duration>.Count;

진정한 확장 방법이 아닙니다. Enum <>이 System.Enum과 다른 유형이기 때문에 작동합니다.


클래스는 static모든 메서드가 확장처럼 작동하도록 할 수 있습니까 ?
Jatin Sanghvi

15
미래의 독자들에게 :의 이름 모호성은 Enum<T>약간 혼란 스럽습니다. 클래스를 호출 할 수도 있으며 EnumUtils<T>메서드 호출은 EnumUtils<Duration>.Count.
Namoshek

46

물론 예를 들어 다음 DescriptionAttribue과 같이 enum값 에 대해 사용할 수 있습니다.

using System.ComponentModel.DataAnnotations;

public enum Duration 
{ 
    [Description("Eight hours")]
    Day,

    [Description("Five days")]
    Week,

    [Description("Twenty-one days")] 
    Month 
}

이제 다음과 같이 할 수 있기를 원합니다.

Duration duration = Duration.Week;
var description = duration.GetDescription(); // will return "Five days"

확장 방법 GetDescription()은 다음과 같이 작성할 수 있습니다.

using System.ComponentModel;
using System.Reflection;

public static string GetDescription(this Enum value)
{
    FieldInfo fieldInfo = value.GetType().GetField(value.ToString());
    if (fieldInfo == null) return null;
    var attribute = (DescriptionAttribute)fieldInfo.GetCustomAttribute(typeof(DescriptionAttribute));
    return attribute.Description;
}

DisplayAttribute Localized GetDescription을 사용하는 것을 제외하고는 거의 정확하게 샘플을 수행 한 확장을 만들려고했습니다. 건배
George

네임 스페이스가 System.ComponentModel 일 뿐이라고 생각하지만 이것은 좋은 대안입니다.
TomDestry

좋은 관점에서 구현 및 확장 코드를 보여 주셔서 감사합니다. 계속해서 구현하려면 다음과 같이 호출 할 수도 있습니다. var description = Duration.Week.GetDescription ();
Spencer Sullivan

31

모든 답변은 훌륭하지만 특정 유형의 열거 형에 확장 메서드를 추가하는 것에 대해 이야기하고 있습니다.

명시 적 캐스팅 대신 현재 값의 int를 반환하는 것과 같은 모든 열거 형에 메서드를 추가하려면 어떻게해야합니까?

public static class EnumExtensions
{
    public static int ToInt<T>(this T soure) where T : IConvertible//enum
    {
        if (!typeof(T).IsEnum)
            throw new ArgumentException("T must be an enumerated type");

        return (int) (IConvertible) soure;
    }

    //ShawnFeatherly funtion (above answer) but as extention method
    public static int Count<T>(this T soure) where T : IConvertible//enum
    {
        if (!typeof(T).IsEnum)
            throw new ArgumentException("T must be an enumerated type");

        return Enum.GetNames(typeof(T)).Length;
    }
}

뒤의 트릭 IConvertible은 상속 계층 구조입니다. MDSN 참조

그의 답변에 대해 ShawnFeatherly에게 감사드립니다.


1
최고의 답변!
마르코 알베스

같게. 확장을 직접 호출하면 작동 MyExtention.DoThing(myvalue)하지만 (예 ) 실제로 열거 형에 연결되지는 않습니다 (예 myvalue.DoThing())
Sinaesthetic

1
참고로, C # 7.3은 이제 일반 유형 제약 조건으로 Enum을 지원합니다
redtetrahedron

7

어떤 것이 든 확장 프로그램을 만들 수 있습니다 object( 모범 사례로 간주되지는 않지만 ). 확장 방법을 방법으로 이해하십시오 public static. 메소드에서 원하는 매개 변수 유형을 사용할 수 있습니다.

public static class DurationExtensions
{
  public static int CalculateDistanceBetween(this Duration first, Duration last)
  {
    //Do something here
  }
}

5

MSDN을 참조하십시오 .

public static class Extensions
{
  public static string SomeMethod(this Duration enumValue)
  {
    //Do something here
    return enumValue.ToString("D"); 
  }
}

7
void열거 형 의 반환 값이 좀 이상합니다. 좀 더 현실적인 샘플에 대해 생각합니다.
psubsee2003 2013 년

3
@ psubsee2003 OP는 확실히 그의 필요에 맞게 이것을 변경할 충분한 지식을 가지고 있습니까? 샘플이 중요한 이유는 초기 질문에 답하는 것으로 충분합니다.
LukeHennerley 2013 년

3
MSDN에서 코드 예제를 이상하게 찾는 유일한 사람입니까? 대부분의 경우 그들이 무엇을하려고하는지 이해하려면 실제 노력이 필요합니다!
Stacked

0

방금 c # https://github.com/simonmau/enum_ext에 대한 열거 형 확장을 만들었습니다.

typesafeenum의 구현 일 뿐이지 만 잘 작동하므로 공유 할 패키지를 만들었습니다.

public sealed class Weekday : TypeSafeNameEnum<Weekday, int>
{
    public static readonly Weekday Monday = new Weekday(1, "--Monday--");
    public static readonly Weekday Tuesday = new Weekday(2, "--Tuesday--");
    public static readonly Weekday Wednesday = new Weekday(3, "--Wednesday--");
    ....

    private Weekday(int id, string name) : base(id, name)
    {
    }

    public string AppendName(string input)
    {
        return $"{Name} {input}";
    }
}

나는 예제가 쓸모가 없다는 것을 알고 있지만 아이디어를 얻습니다.)


0

간단한 해결 방법.

public static class EnumExtensions
{
    public static int ToInt(this Enum payLoad) {

        return ( int ) ( IConvertible ) payLoad;

    }
}

int num = YourEnum.AItem.ToInt();
Console.WriteLine("num : ", num);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.