블로그 이미지
kyeongkyun

calendar

      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    

Notice

'enum'에 해당되는 글 2

  1. 2010/01/18 Enum Type의 버그?(2)
  2. 2009/06/24 열거형을 활용해 보자
2010/01/18 17:00 .NET

 

지난 주말 고객 사에서 문의를 하나 받게 되었습니다. 문제는 여러 개의 매개변수로 오버로드 된 메서드가 이상 작동을 한다는 것이었습니다. 문제는 Enum 타입의 매개변수에 상수 값 0이 입력되면 문제가 발생을 하는 것입니다.  

다음과 같이 enum이 정의 되어 있고 이 enum을 사용하는 메서드가 있습니다.  

 

public enum MyEnum
{
    A=0, B=1, C=2
}
public class MyClass
{
    public void DoWork(object p1)
    {
             Console.WriteLine("Object 매개변수:{0}", p1);
    } 
    public void DoWork(MyEnum p1)
    {
             Console.WriteLine("MyEnum 매개변수:{0}", p1);
    }
}


MyClass는 DoWork라는 두 개의 메서드를 가지고 있으며 매개변수를 통해 오버로드 되어 있습니다. 사용자는 첫 번째 메서드를 사용하여 int 형식의 값을 전달하고 그 결과를 받으려 했습니다.  


MyClass c = new MyClass();
c.DoWork(1);

 

먼저 상수 1을 매개변수로 전달 했습니다. 예상했던대로 첫번째 object를 매개변수로 받는 DoWrok 메서드가 실행 되었습니다.

 

 

문제는 다음 코드에서 발생하게 됩니다. 상수값 0을 입력해 보았습니다.

 

MyClass c = new MyClass();
c.DoWork(0);

  


 

예상과는 다르게 MyEnum 타입을 매개변수로 받는 DoWork 메서드가 실행 된 것입니다. 분명히 상수값 0을 입력하였으나 컴파일러는 0을 Enum 타입으로 인식하고 두번째 메서드를 실행하게 된 것입니다.  

이 문제는 그다지 많이 알려지진 않았지만 ADO.NET에서 SqlParameter를 생성할때도 발생 할 수 있습니다. SqlParameter에는 다음과 같은 오버로드가 존재 합니다.  

 

SqlParameter(string parameterName, object value)
SqlParameter(string parameterName, System.Data.SqlDbType dbType)

 

만약 첫번째 생성자를 사용할 목적으로 value에 상수값 0을 넣게 되면 0은 enum으로 인식하고 SqlDbType의 0번 값인 BigInt를 반환하게 되는 것입니다.  

제 개인적인 생각으로는 상당히 심각한 문제이나 Microsoft에서도 이미 알고 있고 하위 호환성 때문에 수정하지 않고 있다고 합니다.^^

다음 처럼 C# 명세에도 언급되어 있다는 것을 얼마 전에 알게 되었습니다. 


 


 

이를 해결하기 위해서는 외부 변수에 0을 할당하여 사용을 하거나 오버로드시 메서드의 개수를 달리 하는 방법으로 해결 할 수 있습니다.

크리에이티브 커먼즈 라이선스
Creative Commons License

'.NET' 카테고리의 다른 글

Enum Type의 버그?  (2) 2010/01/18
.NET Framework 라이브러리 소스 코드 공개  (0) 2008/01/17
posted by kyeongkyun(kobukii) kyeongkyun
TAG .NET, enum
2009/06/24 21:30 C#

열거형은 멤버 형식을 강력하게 지정하고 코드의 가독성을 향상시키는 데 유용한 상수 값의 집합을 제공합니다

열거형은 상수값의 집합을 제공 하므로 변수의 값을 강력하게 지정하고 코드의 가독성을 향상 시킨다. 일반적으로 열거형을 사용할 때 위의 두 가지 장점 때문에 사용하게 되는데 이번 글에서는 열거형을 사용할 수 있는 케이스에 대하여 알아 볼 것이다.

 

최근 프로젝트에서 UI에 스킨을 적용하게 되었다. 스킨 정보는 서트파티 컨트롤의 열거형으로 지정 되어 있었으며 UI상의 콤보박스에서 스킨이름을 선택하면 해당 스킨으로 화면의 디자인이 변경 되야 한다. 콤보박스에 스킨이름을 추가하고 싶은데 이것이 열거형으로 되어있으니 어떤 방식으로 데이터를 추가해야 할까?

 

다음 예제를 통해 열거형을 순회하고 그 이름을 가져오는 방법에 대해 알아 보겠다.

Enum 타입에는 GetNames()라는 메소드를 제공한다. 이 메소드는 지정된 열거형에서 상수 이름의 배열을 반환한다. 상수이름의 배열, String[]을 제공하기 때문에 이는 DataBoundControl DataSource가 될 수 있다
 

//열거형의 모든 텍스트를 불러와 DropDownList에 추가

ddlFontStyleList.DataSource = Enum.GetNames(typeof(FontStyle));

ddlFontStyleList.DataBind();


위의 예제 코드를 보면 FontStyle 열거형의 모든 상수 값을 읽어와 DropDownListDataSource로 추가하는 것을 볼 수 있다.

FontStyle의 모든 케이스를 직접 작성하여 추가지 않고 FontStyle 열거형의 정보를 읽어와 처리 할 수 있는 것이다.

실행 결과는 다음과 같다.

 



GetNames()
메소드가 String[]을 반환하기 때문에 당연히 foreach구문을 통해 접근하는 것도 가능하다. 다음 코드는 DropDownList에 해당 색상까지 적용된 KnownColor 정보를 추가한다.

 

//열거형(KnownColor)의 모든 텍스트를 불러와 실제 속성을 적용한 후 추가

foreach (string colorName in Enum.GetNames(typeof(KnownColor))) {

         ListItem item = new ListItem(colorName);

         item.Attributes.CssStyle.Add(HtmlTextWriterStyle.Color, colorName);

         ddlColorList.Items.Add(item);

}


다음은 위 코드에 대한 실행 결과다.

 



샘플이 Font와 관련된 열거형을 다루었기 때문인지는 몰라도 위의 코드들을 활용하여 에디터를 제작 해 보는 것도 좋을 것 같다는 생각이 든다.

 

오랜만에 하는 포스팅인데 글이 너무 빨리 끝나는 것 같다. 그래서 간단히 Enum 타입에 적용할 수 있는 확장메소드를 만들어 보도록 하겠다.

 

public partial class _Default : System.Web.UI.Page {

         protected void Page_Load(object sender, EventArgs e) {

                  Grade g1 = Grade.A;

                  Grade g2 = Grade.F;

                  Response.Write(g1.IsFailure().ToString());

                  Response.Write(g2.IsFailure().ToString());

         }

}

public enum Grade {

         A = 5, B = 4, C = 3, D = 2, F = 1

}

public static class TestExtension {

         //낙제 점수

         private static Grade failureGrade = Grade.F;

         //Grade Enum 타입에 대한 확장 메소드

         public static bool IsFailure(this Grade grade){

                  return grade <= failureGrade;

         }

}

 

위의 코드를 살펴보면 Grade라는 열거형이 있고 이는 A, B, C, D, F의 상수값으로 구성되어 있으며 그 값은 5, 4, 3, 2, 1로 되어 있다. 일반적인 열거형에 IsFailure()라는 확장메소드를 추가하였고 현재 열거형의 값이 낙제점 보다 클 경우 true를 반환하고 그렇지 않을 경우 false를 반환하게 된다. 작성 방법은 기존의 확장메소드를 작성할 때 와 동일하다. 이렇게 열거형에 확장메소드를 적용하여 다양한 상황에서 사용할 수 있다.

이번 포스트는 여기까지 입니다.^^
.


크리에이티브 커먼즈 라이선스
Creative Commons License
posted by kyeongkyun(kobukii) kyeongkyun
TAG c#, enum, 열거형
prev 1 next