Re[12]: AlexRK
От: AlexRK  
Дата: 11.07.12 13:18
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, AlexRK, Вы писали:


ARK>>Василий уже ответил за меня: метод Get из third-party либы должен возвращать IAnimal + IPet, а не просто IPet.


AVK>Никому он ничего не должен. Констрейнтов явных нет — значит как повезет.


Признаться, не понимаю вопроса. Метод не возвращает нужный интерфейс IAnimal — все, это ошибка. То же самое если метод не принимает нужного параметра. В чем вопрос-то?

ARK>>>>Кстати, еще момент. Мне не очень нравится ситуация, когда метод возвращает "не знамо что" — интерфейс, за которым непонятно какой класс.

AVK>>>Это называется абстракция. Предлагаешь и ее отменить?
ARK>>ИМХО, не все абстракции одинаково полезны.

AVK>Какие средства абстрагирования ты предлагаешь взамен?


Взамен абстрагирования "изнутри"? Я писал в прошлом посте, предлагается вынести знание о создаваемом классе на тот уровень, на котором оно есть.

AVK>>>Т.е. возможность создания плагинов и аналогичных механизмов хороним в зародыше?

ARK>>Нет, не хороним

AVK>Хороним, потому что они все построены на том, что есть well known абстрактный контракт, и плагины его реализуют.

AVK>Да хоть 10 раз, проблемы это не решает. Код хоста принципиально не может знать, какая реализация будет у абстрактного контракта в конкретном плагине.

Код, использующий плагины, на определенном уровне все равно где-то обязательно знает конкретные типы. Такая точка должна быть. Читает из файла конфигурации названия классов, метаданные или еще что-то в этом роде.
Re[12]: AlexRK
От: AlexRK  
Дата: 11.07.12 13:25
Оценка:
Здравствуйте, artelk, Вы писали:

A>Здравствуйте, AlexRK, Вы писали:


ARK>>Василий уже ответил за меня: метод Get из third-party либы должен возвращать IAnimal + IPet, а не просто IPet.

A>Скорее всего на практике это будет так:
A>
A>interface IAnimal {...}
A>interface IPetOnly {...} //:)
A>alias IPet = IAnimal & IPetOnly;
A>

A>Метод вернет IPet и все довольны, кроме тех кому этот IPetOnly мозолит глаза, т.к. нигде один не используется — только в связке с IAnimal.

Ну, можно и обратную ситуацию вообразить для наследования.
IAnimal, IPet и IPetButNotAnimal. Это если предположить, что нам одинаково часто нужны и IPet, и IPetButNotAnimal.

A>Это все равно, что IList<T> разбить на IReadOnlyList<T> и IChangeOnlyList<T>


Боюсь, не все равно. Кстати, такое разделение списка может быть полезным, на мой взгляд.
Re[13]: AlexRK
От: artelk  
Дата: 11.07.12 13:39
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Здравствуйте, artelk, Вы писали:


A>>Здравствуйте, AlexRK, Вы писали:


ARK>>>Василий уже ответил за меня: метод Get из third-party либы должен возвращать IAnimal + IPet, а не просто IPet.

A>>Скорее всего на практике это будет так:
A>>
A>>interface IAnimal {...}
A>>interface IPetOnly {...} //:)
A>>alias IPet = IAnimal & IPetOnly;
A>>

A>>Метод вернет IPet и все довольны, кроме тех кому этот IPetOnly мозолит глаза, т.к. нигде один не используется — только в связке с IAnimal.
Еще нужно следить, чтоб IAnimal и IPetOnly не пересекались по сигнатурам методов.

ARK>Ну, можно и обратную ситуацию вообразить для наследования.

ARK>IAnimal, IPet и IPetButNotAnimal. Это если предположить, что нам одинаково часто нужны и IPet, и IPetButNotAnimal.
А если IPetButNotAnimal нафиг не нужен, но его все равно придется делать, т.к. язык не поддерживает наследования?

A>>Это все равно, что IList<T> разбить на IReadOnlyList<T> и IChangeOnlyList<T>

ARK>Боюсь, не все равно. Кстати, такое разделение списка может быть полезным, на мой взгляд.
Зачем тебе может понадобится IChangeOnlyList?
Re[14]: AlexRK
От: AlexRK  
Дата: 11.07.12 13:51
Оценка: -1
Здравствуйте, artelk, Вы писали:

A>Здравствуйте, AlexRK, Вы писали:


ARK>>Здравствуйте, artelk, Вы писали:


A>>>Здравствуйте, AlexRK, Вы писали:


ARK>>Ну, можно и обратную ситуацию вообразить для наследования.

ARK>>IAnimal, IPet и IPetButNotAnimal. Это если предположить, что нам одинаково часто нужны и IPet, и IPetButNotAnimal.
A>А если IPetButNotAnimal нафиг не нужен, но его все равно придется делать, т.к. язык не поддерживает наследования?

Тут вопрос только в наименовании, так ведь? Ну да, будет кривоватый IPetOnly. Так я же и привожу обратный пример для наследования — там будет ровно та же кривизна, просто в другом случае — когда нам НУЖНЫ два интерфейса, IPet и IPetButNotAnimal.

A>>>Это все равно, что IList<T> разбить на IReadOnlyList<T> и IChangeOnlyList<T>

ARK>>Боюсь, не все равно. Кстати, такое разделение списка может быть полезным, на мой взгляд.
A>Зачем тебе может понадобится IChangeOnlyList?

Ну мало ли — кому-то может нельзя считывать содержимое, а писать можно. Например — безотносительно списка — пароли можно только записывать, а читать нельзя.
Re[15]: AlexRK
От: artelk  
Дата: 11.07.12 14:10
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Тут вопрос только в наименовании, так ведь? Ну да, будет кривоватый IPetOnly. Так я же и привожу обратный пример для наследования — там будет ровно та же кривизна, просто в другом случае — когда нам НУЖНЫ два интерфейса, IPet и IPetButNotAnimal.

Так я не против алиасов — очень полезно было бы иметь возможность хранить объекты в посях с типом вида IA&IB. Я против замены ими механизма наследования интерфейсов.
Впринципе, если наследование сделать сахаром к генерации соответствующего интерфейса и алиаса, то было бы хорошо.
Т.е. дано:
interface IB : IA
{
  //новые методы
}

Компилятор генерит:
[Invisible]
interface IB_without_IA
{
  //новые методы
}

alias IB = IA & IB_without_IA;

Только нужно еще решить вопрос переопределения методов (то, что делается сейчас через new).
Re[8]: Зачем нужно наследование интерфейсов?
От: Воронков Василий Россия  
Дата: 11.07.12 14:17
Оценка:
Здравствуйте, AndrewVK, Вы писали:

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

AVK>Нет, не предполагает. Рефакторинг никто не отменял.

Предполагает. Ибо расчитывать каждый раз на рефакторинг *интерфейсов* — это уж больно смелое допущение.

AVK>И вопросы, вобщем то, совершенно параллельны конкретно наследованию, и больше относятся к статической типизации в целом.


Эти вопросы не относятся к статической типизации в целом. Они относятся конкретно к наследованию и к тем зависимостям, которые оно вводит.
Re[12]: AlexRK
От: Воронков Василий Россия  
Дата: 11.07.12 14:27
Оценка:
Здравствуйте, AndrewVK, Вы писали:

ВВ>>Вопрос в общем-то остается прежним — зачем *заставлять* так делать? В реальности, это единственный вопрос, на который и нужно ответить в рамках этой темы.

AVK>Затем же, зачем заставлять в статически типизированных языках контролировать соответствие типов. Наследование интерфейсов — неотъемлемая часть контракта. Если я хочу, чтобы любая реализация IPet реализовывала IAnimal (по семантике, проект у меня такой), то я хочу чтобы компилятор это жестко контролировал.

Связать IPet и IAnimal можно и другими способами, кроме наследования. Ты ведь не просто какие-то интерфейсы выставляешь, но и, скажем, проектируешь некое API, которое с ними работает. Ну и в сигнатурах функций указываешь (IPet IAnimal), вместо последнего.

При этом, когда потребуется что-то третье, не окажется, что внезапно надо отрефакторить половину проекта.

ВВ>>К тому же все эти примеры с GetPet/GetItems немного странные. Либо это вообще неполиморфные функции, и тогда они должны возвращать конкретный класс

AVK>Абстракции, видишь ли, бывают многоуровневыми. И GetPet таки полиморфен (реализаций IPet может быть много), просто IAnimal это абстракция уровнем выше.

Значит, он должен возвращать не IAnimal, а что-то другое. Например:

interface IPetProvider<T> where T : IPet
{
  T GetPet();
}

IPetProvider<FishPet>....


Что, кстати, вполне логично, т.к. поставщик рыбок может и не продавать птичек.

AVK>Странно другое — что вы почему то уверены, что достаточно ровно два уровня абстракции на все случаи жизни — одноуровневые интерфейсы и один уровень реализации.


Во-первых, чтобы понять, зачем что-либо нужно, самый простой способ — убрать это, и посмотреть, что получается. Таким образом, например, появилась комбинаторика.
Во-вторых, здесь не два уровня абстракции, а бесконечное множество:

FishPet = IPet IFish IAnimal


ВВ>>, а не интерфейс, либо они являются членами, скажем, генерик-класса, и тогда они тем более не будут возвращать интерфейс, а скорее некое T, на которое будут навешаны констрейнты.


AVK>Да дались вам эти дженерики. Они ничего принципиально не меняют. Дженерики это статический полиморфизм (детали его реализации в дотнете несущественны), а наследование — динамический. Они в общем случае не взаимозаменяемы. И именно из-за попытки заменить одно другим появляются идеи вроде:


Дженерики действительно не причем. Они используются лишь как пример реального механизма, который в ряде случае представляет средства, эквивалетные наследованию.
Ультимативная замена — это вариант структурной типизации, где "единицей" является интерфейс. Т.о. ты выражаешь новые абстракции через комбинацию никак не связанных между собой интерфейсов.

AVK>

AVK>Мне не очень нравится ситуация, когда метод возвращает "не знамо что" — интерфейс, за которым непонятно какой класс. ИМХО, код верхнего уровня всегда должен знать конкретные типы ...

AVK>Вы уж либо крестик снимите, либо трусы оденьте. Либо отказ от динамического полиморфизма полностью, либо он таки есть, неважно как реализован, наследованием/реализацией интерфейсов, или исчислением каких нибудь кортежей типов интерфейсов.

Речь не идет об отказе от динамического полиморфизма. Интерфейсы рассматриваются прежде всего в ООП ключе. А следовательно, там так или иначе рантайм-диспатч, независимо от наличия или отсутствия наследования.

А с утверждением выше я согласен с той оговоркой, что если функция неполиморфна, то не имеет смысла возвращать интерфейс. Если же функция полиморфна, то не имеет смысл ее рассматривать в виде какого-то вырванного из контекста GetItems() без аргументов, который непонятно зачем и для чего. А если расписать целиком всю абстракцию, то есть хорошая такая вероятность, что сразу же найдется и более удачная альтернатива наследованным интерфейсам.
Re[13]: AlexRK
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 11.07.12 17:32
Оценка: +2
Здравствуйте, AlexRK, Вы писали:

AVK>>Никому он ничего не должен. Констрейнтов явных нет — значит как повезет.


ARK>Признаться, не понимаю вопроса. Метод не возвращает нужный интерфейс IAnimal — все, это ошибка.


И? Понимаешь, если я при проектировании сразу заложил наследование IPet от IAnimal, такую ошибку в принципе нельзя сделать, компилятор не даст. Это точно такой же контроль, как и проверка соответсвия сигнатуры реализуемого метода, к примеру. Еще один уровень контроля.

AVK>>Какие средства абстрагирования ты предлагаешь взамен?


ARK>Взамен абстрагирования "изнутри"? Я писал в прошлом посте, предлагается вынести знание о создаваемом классе на тот уровень, на котором оно есть.


Ничего не понял.

AVK>>Да хоть 10 раз, проблемы это не решает. Код хоста принципиально не может знать, какая реализация будет у абстрактного контракта в конкретном плагине.


ARK>Код, использующий плагины, на определенном уровне все равно где-то обязательно знает конкретные типы.


Конечно же нет.

ARK> Такая точка должна быть. Читает из файла конфигурации названия классов, метаданные или еще что-то в этом роде.


И? Как это знание в рантайме поможет компилятору?
... << RSDN@Home 1.2.0 alpha 5 rev. 52 on Windows 7 6.1.7601.65536>>
AVK Blog
Re[12]: AlexRK
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 11.07.12 17:32
Оценка:
Здравствуйте, artelk, Вы писали:

A>Скорее всего на практике это будет так:

A>
A>interface IAnimal {...}
A>interface IPetOnly {...} //:)
A>alias IPet = IAnimal & IPetOnly;
A>

A>Метод вернет IPet

И чем это отличается от наследования?
... << RSDN@Home 1.2.0 alpha 5 rev. 52 on Windows 7 6.1.7601.65536>>
AVK Blog
Re[9]: Зачем нужно наследование интерфейсов?
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 11.07.12 17:32
Оценка: -1
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Предполагает. Ибо расчитывать каждый раз на рефакторинг *интерфейсов* — это уж больно смелое допущение.


Так ты предлагаешь вообще от интерфейсов отказаться? Ну, чтобы их не рефакторить?
... << RSDN@Home 1.2.0 alpha 5 rev. 52 on Windows 7 6.1.7601.65536>>
AVK Blog
Re[14]: AlexRK
От: AlexRK  
Дата: 11.07.12 18:39
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, AlexRK, Вы писали:


AVK>>>Никому он ничего не должен. Констрейнтов явных нет — значит как повезет.


ARK>>Признаться, не понимаю вопроса. Метод не возвращает нужный интерфейс IAnimal — все, это ошибка.


AVK>И? Понимаешь, если я при проектировании сразу заложил наследование IPet от IAnimal, такую ошибку в принципе нельзя сделать, компилятор не даст. Это точно такой же контроль, как и проверка соответсвия сигнатуры реализуемого метода, к примеру. Еще один уровень контроля.


Не понимаю я одно: что конкретно этот контроль дает? Безопасность типов он не повышает. Читабельность тоже не повышает. Зачем он нужен, поясните, пожалуйста. Контроль вида "уж если Get, написанный Васей, вернет IPet, то он точно будет IAnimal, потому что я его (IPet) так реализовал"? ИМХО, сомнительная польза от этого.

AVK>>>Какие средства абстрагирования ты предлагаешь взамен?


ARK>>Взамен абстрагирования "изнутри"? Я писал в прошлом посте, предлагается вынести знание о создаваемом классе на тот уровень, на котором оно есть.


AVK>Ничего не понял.


Это я про ту же "точку знания о конкретных типах".

AVK>>>Да хоть 10 раз, проблемы это не решает. Код хоста принципиально не может знать, какая реализация будет у абстрактного контракта в конкретном плагине.


ARK>>Код, использующий плагины, на определенном уровне все равно где-то обязательно знает конкретные типы.


AVK>Конечно же нет.


Ну хорошо, скажем так: код знает, что будет создан некий класс, реализующий нужный интерфейс. Так что да, как минимум один "магический" метод, из которого выходит неизвестно чего, для поддержки плагинов должен быть (аналог Activator.CreateInstance). А может и не должен... см. ниже.

ARK>> Такая точка должна быть. Читает из файла конфигурации названия классов, метаданные или еще что-то в этом роде.


AVK>И? Как это знание в рантайме поможет компилятору?


Как я понимаю, для JIT проблем быть не должно. Если же речь про "чистую" компиляцию, то да, проблема. Но вообще может оно и не нужно? Это ведь расширение процесса неизвестным кодом. По-моему, от таких вещей надо уходить. В Singularity вроде бы такое расширение запрещено, и это очень правильно.
Re[13]: AlexRK
От: AlexRK  
Дата: 11.07.12 18:43
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, artelk, Вы писали:


A>>Скорее всего на практике это будет так:

A>>
A>>interface IAnimal {...}
A>>interface IPetOnly {...} //:)
A>>alias IPet = IAnimal & IPetOnly;
A>>

A>>Метод вернет IPet

AVK>И чем это отличается от наследования?


IAnimal и IPetOnly не связаны друг с другом. IPet — плоское перечисление интерфейсов. Как следствие, нет приведений типов.
Re[15]: AlexRK
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 11.07.12 20:34
Оценка:
Здравствуйте, AlexRK, Вы писали:


ARK>Не понимаю я одно: что конкретно этот контроль дает?


Я уже отвечал на этот вопрос.

ARK>Контроль вида "уж если Get, написанный Васей, вернет IPet, то он точно будет IAnimal, потому что я его (IPet) так реализовал"? ИМХО, сомнительная польза от этого.


Ну а моя ИМХО говорит, что вовсе даже и не сомнительная.

ARK>>>Код, использующий плагины, на определенном уровне все равно где-то обязательно знает конкретные типы.

AVK>>Конечно же нет.

ARK>Ну хорошо, скажем так: код знает, что будет создан некий класс, реализующий нужный интерфейс.


И что ему это знание дает?

ARK> Так что да, как минимум один "магический" метод, из которого выходит неизвестно чего, для поддержки плагинов должен быть (аналог Activator.CreateInstance).


Ну вот позвал ты Activator.CreateInstance, получил object. Дальше ты что с ним будешь делать?

AVK>>И? Как это знание в рантайме поможет компилятору?


ARK>Как я понимаю, для JIT проблем быть не должно.


Каких проблем? При чем тут джит?

ARK> Если же речь про "чистую" компиляцию, то да, проблема.


А не понимаю, как тебе наличие имени класса в редактируемом пользователем конфигом поможет решить проблемы отсутствия абстракций. Ты методы у динамически созданного объекта как вызывать собираешься? Тоже через рефлекшен?

ARK> Но вообще может оно и не нужно?


А, ну понятно. Больше вопросов не имею.

ARK>В Singularity вроде бы такое расширение запрещено, и это очень правильно.


Нет, не запрещено.
... << RSDN@Home 1.2.0 alpha 5 rev. 52 on Windows 7 6.1.7601.65536>>
AVK Blog
Re[14]: AlexRK
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 11.07.12 20:34
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>IAnimal и IPetOnly не связаны друг с другом.


Абалдеть. Я тож так умею:

interface IPet : IAnimal, IPetOnly {}


ARK>Как следствие, нет приведений типов.


Каких таких приведений?
... << RSDN@Home 1.2.0 alpha 5 rev. 52 on Windows 7 6.1.7601.65536>>
AVK Blog
Re[16]: AlexRK
От: AlexRK  
Дата: 12.07.12 05:59
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, AlexRK, Вы писали:



ARK>>Не понимаю я одно: что конкретно этот контроль дает?


AVK>Я уже отвечал на этот вопрос.


Я не помню, чтобы такой вопрос всплывал в обсуждении. Был вопрос про необходимость наследования, а не про контроль. Вас не затруднит указать ссылку на пост с вашим ответом?

ARK>>Контроль вида "уж если Get, написанный Васей, вернет IPet, то он точно будет IAnimal, потому что я его (IPet) так реализовал"? ИМХО, сомнительная польза от этого.


AVK>Ну а моя ИМХО говорит, что вовсе даже и не сомнительная.


Ну, против ИМХО не попрешь. На одной чаше весов мифический контроль за Васей, на другой — отсутствие исключений при приведении типов. Вам не кажется, что возможность вылета эксепшена — слишком большая цена за такой контроль?

ARK>>>>Код, использующий плагины, на определенном уровне все равно где-то обязательно знает конкретные типы.

AVK>>>Конечно же нет.

ARK>>Ну хорошо, скажем так: код знает, что будет создан некий класс, реализующий нужный интерфейс.


AVK>И что ему это знание дает?


Можно сделать генерик-класс и передать ему созданный объект. Хотя я уже несколько потерял нить разговора.

ARK>> Так что да, как минимум один "магический" метод, из которого выходит неизвестно чего, для поддержки плагинов должен быть (аналог Activator.CreateInstance).


AVK>Ну вот позвал ты Activator.CreateInstance, получил object. Дальше ты что с ним будешь делать?


Не object, а интерфейс. Дальше работаю с ним.

AVK>>>И? Как это знание в рантайме поможет компилятору?


ARK>>Как я понимаю, для JIT проблем быть не должно.


AVK>Каких проблем? При чем тут джит?


JIT может сгенерировать класс в рантайме и подсунуть его нашему генерик-коду. Но все равно — я это уже признал — для этого должен быть "магический" Activator.CreateInstance<T> или аналогичные механизмы. Мы ведь все еще обсуждаем плюсы-минусы (не)возможности выдать из метода "неизвестно что" — просто интерфейс.

ARK>> Если же речь про "чистую" компиляцию, то да, проблема.


AVK>А не понимаю, как тебе наличие имени класса в редактируемом пользователем конфигом поможет решить проблемы отсутствия абстракций. Ты методы у динамически созданного объекта как вызывать собираешься? Тоже через рефлекшен?


Ну почему же, интерфейс будет. Будет метод WorkWithPlugins<T>(T plugin) where T : IPlugin, которому будет передан созданный/загруженный класс.

ARK>> Но вообще может оно и не нужно?


AVK>А, ну понятно. Больше вопросов не имею.


А почему нет? Запускайте отдельный легковесный процесс и общайтесь с ним через каналы (это, разумеется, не про Windows/Linux). По-моему, это куда лучше, чем подцеплять фиг знает что, написанное фиг знает кем, в свое адресное пространство.

ARK>>В Singularity вроде бы такое расширение запрещено, и это очень правильно.


AVK>Нет, не запрещено.


Странно, а вот здесь — http://www.rsdn.ru/article/singularity/singularity.xml
Автор(ы): Galen Hunt, James Larus, Martin Abadi, Mark Aiken, Paul Barham, Manuel Fahndrich, Chris Hawblitzel, Orion Hodson, Steven Levi, Nick Murphy, Bjarne Steensgaard, David Tarditi, Ted Wobber, Brian Zill
Дата: 02.03.2006
Singularity – исследовательский проект Microsoft Research, который начался с вопроса: на что была бы похожа программная платформа, если спроектировать ее на пустом месте, и во главу угла поставить не производительность, а надежность?
— написано такое:

"Драйверы устройств, системные процессы, приложения или расширения работают в собственных SIP и общаются через каналы, предоставляющие функциональность в необходимых пределах"

и

"Закрытые SIP в Singularity не позволяют использовать кодогенерацию во время исполнения".
Re[15]: AlexRK
От: AlexRK  
Дата: 12.07.12 06:05
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, AlexRK, Вы писали:


ARK>>IAnimal и IPetOnly не связаны друг с другом.


AVK>Абалдеть. Я тож так умею:


AVK>
AVK>interface IPet : IAnimal, IPetOnly {}
AVK>


Это не то же самое. Вы не сможете передать в метод "void PetConsumer(IPet pet)" класс "class Cat: IAnimal, IPetOnly".

ARK>>Как следствие, нет приведений типов.


AVK>Каких таких приведений?


Таких:
  var pet = (IPet)animal;  // OOOPS, InvalidCastException
Re[13]: AlexRK
От: artelk  
Дата: 12.07.12 12:33
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, artelk, Вы писали:


A>>Скорее всего на практике это будет так:

A>>
A>>interface IAnimal {...}
A>>interface IPetOnly {...} //:)
A>>alias IPet = IAnimal & IPetOnly;
A>>

A>>Метод вернет IPet

AVK>И чем это отличается от наследования?


Тем, что алиас. В ситуации, когда нам не нужно различать реализацию IPet от одновременной реализации IAnimal и IPetOnly, лучше подходит алиас.
Другой вопрос — бывает ли так, что нужно? Таки бывает, если вспомнить о контрактах.
Пример: контракт для метода Add интерфейса ICollection<T>:
Contract.Ensures(this.Count >= Contract.OldValue<int>(this.Count), "this.Count >= Contract.OldValue(this.Count)");

Count может не измениться для, например, HashSet<T>.
ICollection<T> наследуется интерфейсом IList<T>, для Add усиливается постусловие:
Contract.Ensures(this.Count == (Contract.OldValue<int>(this.Count) + 1), "Count == Contract.OldValue(Count) + 1");

Итого: если переменная имеет тип IList<T>, то это дает нам больше информации, чем если бы она имела тип ICollection<T> & IListOnly<T>, т.е. в этом случае нужно различать.
Re[11]: AlexRK
От: Klapaucius  
Дата: 13.07.12 07:52
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Просто код, который использует плагины, сам должен быть генерик-кодом.


Он может быть дженерик кодом, но не в том смысле в котором вы предлагаете. В T Get() дженерик у нас такой:
forall T. T <: IPet

В случае плагина так не получится. Но получится так:
exist T. T <: IPet

Т.е. мы сможем вернуть из плагина, например, PetBox с этим типом внутри и элиминировать этот ящик, сделав с этим типом что-то, что позволяет интерфейс IPet. При этом "выпустить" тип "наружу" мы не сможем.
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[10]: AlexRK
От: Klapaucius  
Дата: 13.07.12 07:52
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Это называется абстракция. Предлагаешь и ее отменить?


Не в интересах истины, а в интересах правды — абстракция эта дырявая, вплоть до полного несуществования (в динамике, правда, других и не бывает):
(Cat)(IPet)new Cat
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[10]: Зачем нужно наследование интерфейсов?
От: Klapaucius  
Дата: 13.07.12 11:39
Оценка: 68 (3) +2 -1
Здравствуйте, Sinclair, Вы писали:

S>Моему коду нужен ICollection.


ОК.

S>Но я могу мой экземпляр ICollection передать в любой алгоритм, работающий с IEnumerable.


Пока все хорошо...

S>По-моему, это удобно.


... но потом вам этот любой алгоритм вернет IEnumerable, а вашему коду нужен ICollection. Все, приехали.

Сабтайпинг подходит для повсеместной мутабельности, когда ничего интересного не возвращают, а, в основном, на месте переписывают. Как-только начинаются какие-то заигрывания с иммутабельными "объектами" и возвращение чего-то нетривиального становится распространенным сценарием — сабтайпинг сливает со страшной силой, потому как стирает все больше информации о типах, пока не останется Top, к которому сводится все что угодно, но с которым ничего нельзя сделать. При отстутствии динамических кастов получается черная дыра, в которую легко попасть, а выбраться невозможно, а в случае их наличия — динамический глюкодром без каких-либо статических гарантий.
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.