...

воскресенье, 6 апреля 2014 г.

Структурная типизация в C#

Когда я изучал язык Go, мне очень понравилась идея с приведением к интерфейсам по сигнатурам методов (остальная часть системы типов мне не понравилась, слишком примитивная). Это ведь статическая утиная типизация! По научному: структурная типизация.

Если вдуматься, у такого подхода куча недостатков: начиная со сложности реализации и заканчивая нарушением принципа подстановки Лисков. Ведь если у класса есть метод с нужной сигнатурой (включая название), это совсем не значит, что этот метод делает то, что ожидается.

Поэтому в мейнстрим языках, в том числе в C#, структурная типизация не поддерживается. Казалось бы на этом и сказке конец. Но недавно я осознал что в проекте, которым я сейчас занимаюсь, структурная типизация применяется. Подробности под катом.



В проекте метод применяется для работы с геттерами/сеттерами. Конечно его можно использовать и для обычных методов, но вряд ли это даст что-то хорошее.


Итак. Представьте, что у вас есть набор классов, у которых много одинаковых свойств (название и тип).

И ещё больше классов, которым для работы нужны данные из этих свойств. Например: есть класс DataItem с автосвойствами A, B и C. И класс Calculator, которому требуется значение свойства A, чтобы на его основе что-то вычислить и занести в B. А про C ему знать не надо. Также ему не надо знать и про класс DataItem, т.к. он может использоваться и с другими классами у которых есть A и B.


Как это реализовать? Заранее объявить для каждого, из таких свойств интерфейс, и каждый класс с такими свойствами пометить, как реализующий соответствующие интерфейсы. А методы классов потребителей объявлять generic-ами.


Реализация:



interface PropertyA{
int A {get; set;}
}

class DataItem: PropertyA, PropertyB, PropertyC{
public int A {get; set;}
public bool B {get; set;}
public string C {get; set;}
}

...

void Calculate<T>(T data) where T: PropertyA, PropertyB{
data.B = data.A > 0;
}


Всё просто: указывая ограничения generic параметра можно собрать подходящий набор полей, и объект любого класс их реализующий передать в такой метод без всяких приведений.


Сложнее понять зачем это может пригодиться, и не является ли ситуация, когда подобная техника нужна, ещё одним запахом кода.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий