티스토리 뷰

 

C#의 제네릭을 사용하면 컴파일 타임에 타입을 미리 체크하여 에러를 사전에 잡을 수 있고, 컴파일러가 직접 타입을 캐스팅해줘서 편하고 다른 타입이지만 동일한 코드를 사용할 때, 코드 재사용성을 높여줘서 아주 유용하다.

그렇다면 왜 이렇게 편한 제네릭 인터페이스가 있는데 논제네릭 인터페이스도 같이 구현하라고 하는걸까?


논제네릭 인터페이스를 함께 구현해야 하는 이유

제네릭이 생기기 이전에 개발된 코드들을 무시할 수 있다면 좋겠지만 유감스럽게도 무시하는 것이 어려운 것이 사실이다.

새로운 라이브러리를 개발할 때 제네릭 타입뿐 아니라 고전적인 방식도 함께 지원하다면 라이브러리의 활용도를 더 높일 수 있다.

만약 제네릭 타입이 아닌 방식도 지원하겠다고 결정했다면 다음 3가지 요소에 대해서 논제네릭 방식을 지원해야 한다.

1) 클래스와 인터페이스

2) public 속성

3) serialize 대상이 되는 요소

어떻게 제네릭 방식에 논제네릭 방식을 추가하는가?

public class Name : IComparable<Name> { public string First { get; set; } public string Last { get; set; } public string Middle { get; set; } // IComparable<Name> 멤버 public int CompareTo(Name other) { if (Object.ReferenceEquals(this, other)) { return 0; } if (Object.ReferenceEquals(this, null)) { return 1; // null이 아닌 객체는 null보다 크다. } int rVal = Comparer<string>.Default.Compare(Last, other.Last); if (rVal != 0) return rVal; rVal = Comparer<string>.Default.Compare(First, other.First); if (rVal != 0) return rVal; return Comparer<string>.Default.Compare(Middle, other.Middle); } }

Name이라는 클래스에 객체의 선후 관계를 정의하는 IComparable<T>의 인터페이스를 적용한 코드이다. 최근 코드만을 지원하다면 이대로도 충분하겠지만 이번 파트는 제네릭 이전에 개발된 코드들에게도 지원이 되도록 코드를 짤 생각이다.

따라서 IComparable 인터페이스도 추가해볼 것이다.

public class Name : IComparable<Name>, IComparable { public string First { get; set; } public string Last { get; set; } public string Middle { get; set; } // IComparable<Name> 멤버 => 생략 public int CompareTo(Name other) { ... } // IComparable 멤버 int IComparable.CompareTo(object obj) { if (obj.GetType() != typeof(Name)) throw new ArgumentException("Argument is not a Name object"); return this.CompareTo(obj as Name); } }

위 코드에서 IComparable.CompareTo(object obj)라고 명시적으로 인터페이스를 구현하였음에 주목해보자. 이렇게 하면 실수로 제네릭 인터페이스 대신 논제네릭 인터페이스를 사용하는 것을 방지할 수 다.

이런 식으로 코드를 작성하면 논제네릭 타입의 인터페이스에 포함된 메서드를 호출하기 위한 유일한 방법은 명시적으로 IComparable 인터페이스 참조를 통해서 메서드를 호출하는 경우뿐이다.

결론

대부분의 경우 논제네릭 인터페이스를 추가하는 작업은 적절한 원형의 메서드를 추가하는 수준에서 간단히 해결된다.

.NET Framework 1.0에서부터 제네릭이 구현되었다면 좋겠지만 이미 지나간 과거일 뿐이다. 제네릭이 포함되기 전에 개발된 수많은 코드가 이미 존재하고 새롭게 작성하는 코드가 예전에 개발된 코드와 함께 사용해야 한다면 반드시 논제네릭 타입의 인터페이스를 구현해야 한다.

그리고 논제네릭 인터페이스를 구현할 때는 반드시 명시적인 방법으로 구현하는 것이 좋다.


전체적인 내용을 전부 이해하기에는 조금 힘들어서 이해가 되는 부분만 정리하여 중요한 부분을 빠뜨렸을 수도 있습니다.

Effective C#을 공부하는 분들은 참조용으로만 이 글을 참고하시고 책을 자세히 들여다보길 추천합니다.

참조 - Effective C# <강력한 C# 코드를 구현하는 50가지 전략과 기법, 이펙티브>, 빌 와그너, 김명신, 한빛미디어

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
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
글 보관함