Здравствуйте, samius, Вы писали:
V>>Я не прав был, что не изучил её (простыню) всю? ))
S>Сам же и ответил. Не поняв, ЗАЧЕМ, изучил всю, вынес вердикт не о том, о чем была дана ссылка и контекст.
Потому что это было уныло — расписывать.
Я хорошо понял зачем.
Унылость была в том, что коллега не расписал свой аргумент, т.е. отвечать было не нечего, а не на что. Начался отрезок бессмыслицы в обсуждении.
Я его просто ткнул носом в слабость его аргумента и удивился потом с того, что коллега даже не понял, во что именно я его ткнул. ))
И еще показал, что я подобных флуктуаций его сознания уже ожидал:
http://www.rsdn.org/forum/flame.comp/6662410.1
Там действительно, лишь флуктуация.
Т.е. человек помнит "трюк" насчет ограничений генерик-аргументов, но не помнит, куда и как его можно применять.
V>>Вместо такого фокуса коллега мог назвать конкретный метод конкретного типа и никаких ссылок не надо — кому попервой и даже любопытно, пусть смотрит сам. А остальным, кто еще 12-15 лет назад это всё уже прожевал и выкакал, сорри, тому банально не любопытно глазеть на подобный код.
S>Коллега понадеялся что контекста обсуждения было достаточно. А в отношении любопытства остальных — согласен. Возможность — юслес на 99% (ИМХО).
Коллега не умеет формулировать свои мысли. Если бы он попытался формально расписать свой аргумент, то САМ увидел бы, что его аргумент НЕ канает. Бо в хорошем вопросе содержится половина ответа. И тут как раз тот случай.
Сам разве не обратил внимания, что между List<T> и ограничением IEquatable<T> нет никакой связи на уровне типов языка.
Он ведь правильно пишет (по наитию, скорее):
Как он (comparer) там создаётся вообще пофигу.
"Пофигу", потому что ему хочется проигнорить вот этот "разрыв" в системе типов, из-за чего, собсно, и подключается рефлексия.
Но оно не пофигу, коль он взялся опровергать вот это:
Собсно, вообще таких алгоритмов мало, которые можно выразить в дотнете для value и ref-типов в генериках и они будут корректно работать в обоих случаях.
Потому что из-за отсутствия связи на уровне типов в этом месте НЕЛЬЗЯ подать value-type GenericEqualityComparer<T> where T : IEquatable<T>, даже если бы сигнатура метода была примерно такая:
class List<T> {
public int IndexOf<TComparer>(T value, Comparer comparer) where TComparer : IEqualityComparer<T> {...}
...
}
Т.е. в этом месте можно было бы подать лишь НЕ генерик-реализацию в случае value-type компаратора, т.е. его аргумент аннигилируется без моей помощи. ))
Потому что требуемое ограничение надо было бы
распространить выше:
class List<T> where T : IEquatable<T>
что являлось бы суровым ограничением.
Итого, что мы имеем:
* В самом алгоритме целевого метода используется техника, описанная мною
тут и
тут.
Оттуда:
я и сам смогу тебе привести сходу пример, где такой полиморфизм сможет разресолвится статически в дотнете, я уже озвучивал — это при использовании технологии "объекта-словаря операций" (и в приводимых к этой концепции сценариях), где сам такой объект представлен value-типом. Ну не популярная эта техника нифига в дотнете. Там никто не таскает в логике эти словари рядом с целевыми объектами, везде идёт попытка работать с объектами напрямую. А когда напрямую, то возвращаемся к самому первому моему утверждению:
Собсно, вообще таких алгоритмов мало, которые можно выразить в дотнете для value и ref-типов в генериках и они будут корректно работать в обоих случаях.
Потому что получается так, что лишь теми операциями, которыми обложили базу объекта (интефейс интерфейса или публичный интерфейс базового класса) и можно оперировать. И шаг вправо-влево сделать вааще никак.
Но спорить с подобными утверждениями тоже надо уметь. Пытаясь мне показать, что такие алгоритмы все-таки есть, вы показываете банальное невладение логикой.
* Мне приводят пример, где GenericEqualityComparer<T> создаётся через рефлексию,
потому что система типов не позволяет указать его явно в исходнике.
* В целевом алгоритме НЕТ никакого трюка по вызову методов целевого типа T.
* Все операции делаются через т.н. "словарь операций", где сам словарь НЕ обязан быть генерик-словарём, там используется обычный ООП-интерфейс.
* вызов методов у целевого T происходит только здесь:
internal class GenericEqualityComparer<T> : EqualityComparer<T> where T : IEquatable<T>
{
public override bool Equals(T x, T y)
{
if (x != null)
{
if (y != null) return x.Equals(y);
return false;
}
if (y != null) return false;
return true;
}
}
Что в случае специализации в рантайме конкретным value-типом, отличным от Nullable<T2>, например, простым int (не суть важно, просто пример конкретного типа) даст вот такой код:
public override bool Equals(int x, int y)
{
return x.Equals(y);
}
Вот ЭТО и есть пример "алгоритма"?
===================
Я бы мог всё это дать сразу, но тут сработал такой момент, что когда собеседник "претендует" на некий уровень (а сходу взятый надменно-язвительный тон и регулярное переименование заголовков сообщений в некие "намеки" означает именно это, верно?), то сей "уровень" надо ж уметь поддерживать, не? ))
В общем, я не должен был всю эту банальщину тут расписывать. Ведь со стороны дотнета выступал не я. А то получается, что я должен был начать сам с собой спорить, бо оппонент за себя не тянет.
V>>Дотнет на сегодня — это уже довольно древняя технология, об этом надо таки помнить. Оно ведь даже скорее раздражает, когда собеседник пытается спорить и аргументировать вот на таком уровне.
S>80% технологий еще древнее. Если не больше.
Верно. Поэтому совсем уж заходить на банальности, а тем паче начинать плавать по ним — это банально моветон.
Тем более, плавать со "своей стороны баррикад". ))
V>>В общем, озвуч он членораздельно свой аргумент, и я сходу бы ему и ответил, почему его аргумент кривой, косой и не канает. Потому что, с начала всех начал, его пример НЕ является примером:
V>>1. там в любом случае происходит вызов метода интерфейса;
S>Вероятно, но вызов метода интерфейса не через интерфейс там тоже происходит.
И ты, Брут?
Нет, не происходит.
С точки зрения метода IndexOf, мы вызываем методы "черного ящика" — поданного извне словаря операций. Вызовы метода по ограничениям — это уже подробности реализации этого черного ящика и никак не связаны с целевым алгоритмом. Более того, уже показал выше, почему этот "черный ящик" не может иметь генерик-реализацию value-type в системе типов, т.е. у нас тут получаются ДВА независимых разных алгоритма, работающих совместно.
Т.е., мы заведомо имеем дело с "нетипизированным параметрическим полиморфизмом".
Подробно я описывал тут:
http://www.rsdn.org/forum/flame.comp/6680620.1
Блин, ну вот целиком пример (заставляете тратить время на запуск Студии, бо я уже и сам начинаю сомневаться, ы-ы-ы):
struct GenericEqualityComparer<T> : IEqualityComparer<T> where T : IEquatable<T>
{
public bool Equals(T x, T y)
{
if (x != null)
{
if (y != null) return x.Equals(y);
return false;
}
if (y != null) return false;
return true;
}
public int GetHashCode(T obj)
{
throw new NotImplementedException();
}
}
class MyList<T>
{
public int IndexOf<TComparer>(T value, TComparer comparer) where TComparer : IEqualityComparer<T>
{
return 0; // заглушка
}
// Не компиллируется!
public int IndexOf<TComparer>(T value)
{
return IndexOf(value, new GenericEqualityComparer<T>());
}
}
А не, всё верно, не компиллируется нифига.
Кароч.
Именно из-за нетипизированной природы параметрического полиморфизма в предлагаемом МНЕ примере-аргументе мы НЕ МОЖЕМ вызывать методы типа T в теле методов MyList<T>.
Ву а ля? Или еще нет?
Но фиг с ним, это всё банальности и я в шоке, что их потребовалось расписать настолько подробно на 15-й год существования дотнета. Дело не только в этом. Различная null-default(T) семантика value и ref типов накладывает свои дополнительные ограничения и тоже резко сужает класс алгоритмов, которые можно было бы выразить прямо из Т, без прибегания к технике "словарей операций", которые, цитирую сам себя:
... в концепции дотнетного ООП такая техника выглядит заимствованием из чужеродного ФП.
Т.е., те фишки ФП, которые не руинят ООП — они в практику дотнета таскаются с удовольствием, смотрю. Остальные практики игнорятся, хотя именно такая реализация параметрического полиморфизма требует именно таких практик.
И я имел ввиду больше вот эти ограничения на разницу в семантике (в одном случае идёт прямая адресация, в другом косвенная), которые не всегда просто преодолеть — оформить непосредственно в виде генерик-кода БЕЗ прибегания к посторонним "словарям операций". Каждый такой словарь — это костыль. В С++ можно обойтись без него, в этом была суть уже моего аргумента. Хотя, можно и с таким же точно костылём — но в С++ хоть есть выбор.
В общем, всё нужное я уже более одного раза говорил ранее...
Просто топик расползся и оно местами сильно по топику раскидано. ))
V>>2. дефолтный компаратор порождается через рефлексию; особенно весело сие после пространных рассуждений коллеги о "безопасной компиляции";
S>Как создается дефолтный компарер — не имеет отношения. Тем более, что он кэшируется.
Т.е., таки, Брут. ))
Имеет в том плане, что может быть создан ТОЛЬКО через рефлексию.
Кеширован или нет — отмазки, это же просто некое инженерное решение-следствие, т.е. уже не принципиально в этом споре.
Более того, само наличие отдельного компаратора, даже для случая встроенных типов — это ой. Потому что в теле самого List<> мы беспомощны.
V>>3. коллега пытался аргументировать об одинаковой работе для случая value-type и ref-type, но приводит такой пример, где методы типа Т не вызываются вовсе, а вызываются методы исключительно ref-типа IComparer<T> (в теле генерик-метода);
S>а методы IEquatable<T> каким образом вызываются? О них ведь речь была.
Методы IEquatable<T> в целевом алгоритме не вызываются никак, даже после Джитта, увы. Вызываются методы черного ящика, причем, исключительно как виртуальные. Т.е., что там на "другой стороне" уже не принципиально.
Т.е., в обсуждаемом примере через "водораздел" ООП-полиморфизма происходит выход на ad hoc полиморфизм. А вот последний может, в свою очередь, может быть реализован и через параметрический полиморфизм и через что угодно. Одно плохо — в системе типов языка последнее невыразимо вообще никак.
V>>Этого коллеге показалось мало и его стало заносить далее: " ты даже на джуниора не потянул бы, ты совершенно не понимаешь происходящего".
V>>Мамая мия.
S>Я полагаю что вы говорили о чем-то разном, подразумевая что об одном и том же.
Я полагаю, что коллега плохо понимает, о чем речь, но обвиняет в плохом понимании окружающих.
Причем, ответвление на vector<> показало вообще кошмар в плане дедуктивных способностей и навыков ведения спора / аргументирования.
Вот тут примерно так же — вместо обсуждения сабжа коллега радостно зацепился за мою фразу "вызов Equals у базового Object", хотя к сути происходящего в методах List<T> оно вообще не имело никакого отношения. Даже само это цепляние было самоподставой (чел повелся на троллинг),
ведь в системе типов языка нам доступна только реализация указанного мною ObjectEqualityComparer и я недвусмысленно на это намекал.
Похоже, ты тоже не понял тот "тонкий" троллинг с моей стороны... Но ты-то ладно, это было обсуждение не с тобой, ты не обязан вдумываться в чужие споры.
Кароч, это я уже сам себя веселил, видя полнейшую слепоту оппонента колеги Qbit86.
Просто троллинг был уже нифига не тонкий, вот в чем был самый юмор ситуации, как по мне.
Но все-равно коллега так и не увидел, в чем там собака зарыта... Ну и фиг с ним, значит и не хотел...
Но потом заканчивает своё непонимание рассуждениями о том, что я даже на джуниора не тяну.
Блин, куда катится мир?
На Украине пещерные люди отодвинули грамотных. На форуме тоже порой просто засилье, скажем так, глубоко несообразительных людей... что ваще происходит-то??? )))
V>>В итоге, коллега заслуженно был подвергнут нещадной обструкции.
V>>Причем, весьма мягкой, ИМХО, учитывая происходящее целиком. ))
S>Мягко, но нещадно. Интересно.
Мягкой по форме, нещадной по содержанию. Так бывает. ))
Можно было бы и форму попрямее выбрать, бо это всё просто сюрр для, казалось бы, аж программиста...
V>>Хотя, если упустить весь рисунок развития ситуации, согласен, моя реакция может показаться странной. Там надо на десяток постов вверх подниматься и смотреть на картинку целиком.
S>Смотрел вчера, картина не стоит того.
Я уже высказывал своё восхищение твоими манерами, но нет.
Понимаешь, дело вовсе не в том, что коллега чего-то не понимает.
Невладение какой-то инфой здесь и сейчас — оно ведь совершенно не страшно.
Я бы даже сказал — это полная ерунда, не принципиально ни разу.
Страшно, другое — когда и не хотят владеть.
Еще более страшно, когда оппонент сходу переходит к мелким гадостям — подколкам, язвительности, троллингу и т.д. и т.п. на ровном (на тот момент) месте. С чего бы это, ы?
Вот такие мелкие подлости, да еще от не слишком сообразительного человека — оно приобретает эффект синергии при формировании ответного отношения.
Это же всё личные кач-ва человека, и они тут сверкают просто как россыпь бриллиантов.
В ответ на подобные манеры я обычно включаю свою душевную простоту почти сельского парня, коим и являюсь. ))