C# Covariance(공변성), Contravariance (반공변성)
C# 으로 이런저런 프로젝트를 진행하면서... 자주 쓰진 않지만 까먹어서 여기다가 잘 까먹는 내용을 정리해두고자 한다.
* Covariance(공변성), Contravariance (반공변성)
https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance
위 사이트에 내용이 잘 정리되어 있다.
단어가 꽤 어려워 보이는데...
사실 공변성은 일반적인 Polymorphism 의 특성이라 이해하기가 쉽고, 반공변성은 직관적으로는 이해하기가 어렵다.
Covariance (공변성)
Enables you to use a more derived type than originally specified.
Contravariance (반공변성)
Enables you to use a more generic (less derived) type than originally specified.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class Base { } public class Derived : Base { } public static Derived MyMethod(Base b) { return b as Derived ?? new Derived(); } Func<Base, Derived> f1 = MyMethod; // Covariant return type. Func<Base, Base> f2 = f1; Base b2 = f2(new Base()); // Contravariant parameter type. Func<Derived, Derived> f3 = f1; Derived d3 = f3(new Derived()); | cs |
아래는 또 다른 예...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // Covariance. IEnumerable<string> strings = new List<string>(); // An object that is instantiated with a more derived type argument // is assigned to an object instantiated with a less derived type argument. // Assignment compatibility is preserved. IEnumerable<object> objects = strings; // Contravariance. // Assume that the following method is in the class: void SetObject(object o) { } Action<object> actObject = SetObject; // An object that is instantiated with a less derived type argument // is assigned to an object instantiated with a more derived type argument. // Assignment compatibility is reversed. Action<string> actString = actObject; | cs |
Covariance 의 경우 좌변의 부모가 우변의 자식을 품는 형태가 되는데...
Contravariance 의 경우 좌변의 자식이 우변의 부모를 품는 형태가 된다.
* Contravariance 는 직관적이지 않아서 사실 이해하기가 어렵다.. C# 에서 지원하는 기능중 하나이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // Covariant interface. interface ICovariant<out R> { } // 1. // Extending covariant interface. interface IExtCovariant<out R> : ICovariant<R> { } // 2. // Implementing covariant interface. class Sample<R> : ICovariant<R> { } ICovariant<Object> iobj = new Sample<Object>(); ICovariant<String> istr = new Sample<String>(); // You can assign istr to iobj because // the ICovariant interface is covariant. iobj = istr; | cs |
1. interface ICovariant 를 generic 형태로 만들었는데 out R 이라는 인자를 받게끔 되어 있다.
2. 그리고 ICovariant 를 상속받은 IExtCovariant 도 같은 형태를 취하게 된다.
코드 마지막의 iobj = istr 은 Covariance 의 특성이다.
정리하긴 했는데... 쓸 일은 별로 없었던 것 같다.
어떤 언어만의 특성이 강하게 반영된 코드를 작성하면... 그 언어가 제공하는 특성을 최대한 활용할 수 있는 장점이 있지만...
나중에 그 언어에 익숙하지 않은 다른 후임 개발자가 이 코드를 보게되면 유지보수가 어려운 단점이 있다고 생각한다.
1. 따라서 다른 개발자에게 공개할 필요가 없고, 캡슐화가 가능한 코드에는 이런 방법을 고려해보면 좋을 것 같고...
2. 많은 개발자와 공동작업을 진행하고 앞으로 후임 개발자의 투입도 고려해야 하는 상황이라면... 복잡하고 난해한 코드들은 아무리 기능이 좋아도 오히려 독이 된다고 생각한다.
'프로그래밍 > 분류없음' 카테고리의 다른 글
C# Boxing, Unboxing (0) | 2017.09.06 |
---|---|
C# EventHandler 의 Accessor (0) | 2017.09.06 |
C# Covariance(공변성), Contravariance (반공변성) (0) | 2017.09.06 |
git 내가 자주 쓰는 명령 정리 (0) | 2017.08.22 |
Python 패키지 오프라인 다운로드 및 설치 (0) | 2017.08.21 |
Python 패키지 업데이트 (Windows) (0) | 2017.02.15 |