안녕하세요! 정말 오랜만입니다.

이렇게 오랜만에 글을 쓰는 것은 제 귀찮음 때문이 아닐까 싶습니다.. ㅠㅠ 

변명이라고 하기엔 유격훈련도 있었고.. 인터넷을 자주 못해서.. 라고 말하고 싶네요.


바로 본론으로 들어가보겠습니다.



이번 글에서는 형식 매개 변수에 조건을 거는 방법에 대해 알아보려고 합니다.


형식 매개 변수? 제네릭?

제네릭에 대해 기초가 잡히지 않으신 분들은 제네릭(Generic) 이란 무엇일까? 글을 봐주시기 바랍니다!



기초적인 제네릭 선언 방법은 다음과 같습니다.

클래스, 인터페이스, 구조체, 메서드와 이벤트 및 대리자에 사용이 가능합니다.

identifier class_name<TypeParameters ...> {
    ....
}



제네릭은 제네릭 자체로도 정말 유용하지만, 여기에 형식 매개 변수를 원하는 조건에 맞는 것으로만 선택하도록 할 수 있다면 제네릭은 더욱 빛을 발하게 됩니다.


형식 매개 변수에 제약 조건을 거는 것은 어렵지 않습니다.

identifier class_name<TypeParameters ...> where TypeParameterName : identifier_or_type {
     ....
}



이렇게 추상적인 코드로 나타내니깐 이해하기가 어렵네요. 그럼 하나씩 분리해서 설명해 드리도록 하겠습니다.


identifier 부분은 말 그대로 식별자를 나타냅니다.

여기서 식별자란 의미는 이름이 아니라 struct, interface, class 등의 형식을 선언할 때 사용되는 것을 말합니다.


class_name 및 TypeParameters 부분은 형식 이름과 형식 매개 변수를 뜻합니다.

제네릭을 사용할 때에는 형식 매개 변수의 갯수 제한이 없기 때문에 여러 개가 사용될 수 있으므로 복수형(s)으로 표기했습니다.


where TypeParameterName : identifier_or_type

이 부분이 이번 글의 핵심이라고 할 수 있습니다.


where 이라는 키워드는 뒤에 나오는 형식 매개 변수에 조건을 걸어주는 역할을 합니다.

그리고 가장 뒤에 있는 identifier_or_type 의 경우, 형식 매개 변수에 걸리는 조건을 나타냅니다.


이 때 사용할 수 있는 조건은 다음과 같습니다.

조건

설명

 where <NAME> : struct

 <NAME>에 대응하는 형식 매개 변수는 반드시 값 형식이여야 합니다.

 where <NAME> : class

 <NAME>에 대응하는 형식 매개 변수는 반드시 참조 형식이여야 합니다.

 where <NAME> : <TYPE>

 <NAME>에 대응하는 형식 매개 변수는 <TYPE> 형식이거나, <TYPE> 형식에서

 파생되거나 또는 인터페이스인 경우 <TYPE> 인터페이스를 구현해야 합니다.


* where <NAME> : <TYPE> 조건에 대한 제약 사항

  • 상속 불가능(sealed)으로 표시된 형식을 사용할 수 없습니다.
  • 구조체 및 정적 클래스도 사용할 수 없습니다.
  • 특수 형식(object, Array, Delegate 등)을 사용할 수 없습니다.
  • 추가로, class 및 struct 조건은 같이 사용될 수 없습니다. class 또는 struct 조건은 반드시 제약 조건 문맥의 처음에 위치해야 합니다.




그리고, 이 제약 조건은 형식 매개 변수 하나에만 적용할 수 있는게 아닙니다. 또한, 한 개의 제약 조건만 걸 수 있는 것도 아닙니다.

class GenericClass<TIn, TOut>
    where TIn : class
    where TOut : Stream, TIn {

}



위 코드처럼 두 개의 형식 매개 변수를 필요로 하는 형식에는 두 개의 제약 조건, 그리고 각 제약 조건에 따라서 한개 이상의 제약 조건을 설정할 수가 있습니다.


여기서 주의해야 하실 점은 where 의 조건 부분은 콤마(,) 로 구분하는 반면 where <NAME> : <TYPE> 인 전체 조건문은 띄어쓰기 또는 줄바꿈으로 구분된다는 것입니다.


맞는 표현:

class GenericClass<TInTOut>
    where TIn : class
     where TOut : StreamTIn {

}


틀린 표현:

class GenericClass<TInTOut>
    where TIn : class, where TOut : StreamTIn {

}

이유: where 조건문이 띄어쓰기 혹은 줄바꿈 문자가 아닌 콤마로 구분되었음


이로써 형식 매개 변수에 제약 조건을 다는 방법을 알아봤습니다.

이 방법을 이용하면 예기치 않은 형식을 형식 매개 변수로 넘기는 상황을 방지할 수 있겠죠?


긴 글 읽어주셔서 감사합니다! 즐거운 프로그래밍 하세요!!

+ Recent posts