- PVSM.RU - https://www.pvsm.ru -
О вариантности в C# написано множество хороших статей. Но читая о её проявлениях в разных аспектах языка я столкнулся с тем, что каждый раз её представляют мне несколько иначе, чем в прошлый раз. Поэтому мне не удавалось сформулировать чёткое определение — шаблон, который хорошо соответствовал бы каждому проявлению вариантности, с которым я сталкиваюсь, и позволил бы мне держать в голове лишь одну концепцию, вместо набора различных ситуаций. Эта заметка — моя попытка сформулировать нужный шаблон.
Вариантность — это свойство преобразования типов операторами.
Оператор — любая сущность языка C#, преобразующая типы данных в производные от них. Например, оператором явялется T[]
создающий производный тип массива из типа T
, Action<T>
создающий производный тип действия с одним параметром из T
. Оператор группы методов T MyMethod(U)
, преобразует сразу два типа: T
, создавая производный тип возвращаемое значение и U
, создавая производный тип аргумент метода. Те же преобразования осуществляет и оператор создания типа делегата Func<U,T>
. Но в последнем случае эти преобразования отличаются от первого своими своиствами — вариантностью.
Чтобы описать все формы, которые может принимать свойство вариантности необходимо определить, как типы могут соотноситься с друг другом. Здесь и далее под типом я понимаю любой ссылочный тип или производный от него. Если экземпляр типа T
можно заменить экземпляром типа U
, то мы будем считать, что U < T
. Если экземпляр U
можно заменить экземпляром T
, то U > T
. Если обе замены возможны, то U = T
. Если ни одна не возможна, то типы T
и U
не сравнимы.
Преобразование, осуществляемое оператором, является:
Несколько примеров применения такого определения:
T[]
ковариантно преобразует T
, поэтому можно заменить экземпляр Object[]
на экземпляр String[]
Action<T>
контравариантно преобразует T
, поэтому можно заменить Action<String>
на Action<Object>
Func<T,U>
ковариантно преобразует возвращяемый тип U
и контравариантно преобразует тип передаваемого аргумента T
. Поэтому можно заменить Func<String,Object>
на Func<Object, String>
U MyMethod(T t)
инвариантно преобразует как возвращаемый тип T
, так и тип передаваемого аргумента U
. Поэтому нельзя перегрузить метод Object MyMethod(String)
методом String MyMethod(Object)
Надеюсь, что сформулированное определение сможет помочь в изучении вопроса вариантности, на ряду с ресурсами, которые я использовал для создания этой заметки:
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/pesochnitsa/82778
Ссылки в тексте:
[1] Eric Lippert's Blog, Covariance and Contravariance in C#, Part One: http://blogs.msdn.com/b/ericlippert/archive/2007/10/16/covariance-and-contravariance-in-c-part-one.aspx
[2] Eric Lippert's Blog, Covariance and Contravariance in C#, Part Two: Array Covariance: http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx
[3] Eric Lippert's Blog, Covariance and Contravariance in C#, Part Three: Method Group Conversion Variance: http://blogs.msdn.com/b/ericlippert/archive/2007/10/19/covariance-and-contravariance-in-c-part-three-member-group-conversion-variance.aspx
[4] Eric Lippert's Blog, Covariance and Contravariance in C#, Part Four: Real Delegate Variance: http://blogs.msdn.com/b/ericlippert/archive/2007/10/22/covariance-and-contravariance-in-c-part-four-real-delegate-variance.aspx
[5] Джон Скит, C# Для Профессионалов: http://csharpindepth.com/
[6] Wikipedia, Covariance and contravariance (computer science): http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)
[7] MSDN, Covariance and Contravariance: https://msdn.microsoft.com/en-us/library/ee207183.aspx
Нажмите здесь для печати.