Здравствуйте, VladD2, Вы писали: VD>Синклер... Что-то ты разошелся.
VD>Это называется — заблуждение. А то и просто "несовпадение мнений".
Заблуждение — это когда, к примеру, Рихтер делает утверждение, оказавшееся ложным. Например, "размер system.IntPtr не зависит от платформы". Ну то есть если он знает, что оно ложное, то это — вранье, а если не знает — то честное заблуждение. (Примечание: Рихтер такого на самом деле не утверждает. Это вымышленный пример.)
А вот очевидно тупиковые решения, из которых последуют массовые неудобства — это бред. Не, ну я могу назвать это как-то политкорректно, например "не вполне продуманные рекомендации", но сути это не изменит.
Ход мысли, приводящий к таким "не вполне продуманным рекомендациям", традиционно называется в нашей русскоязычно-программистской среде "наркоманией".
Я бы мог, опять же, завуалировать мое профессиональное мнение привычной риторикой типа "что курил Рихтер перед этим?", но сути бы это опять же не изменило.
Кроме того, привычный к забористой ругани завсегдатай ФП вряд ли сможет оценить всю глубину моего негодования по поводу данных предложений Рихтера, смягчи я формулировку.
А меня крайне напрягает эта магия имени. Если бы с предложением реализовать дефолтный Equals как проверку на совпадение типа выступил рядовой аноним, его бы тут подняли на смех (и поделом). Но сейчас это предложение обрело священный ореол знаменитого имени — и ты погляди, с каким усердием народ защищает эту дурость! Уже неканонические трактовки сочиняются, мол он не это имел в виду.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, _d_m_, Вы писали:
___>Closer — поясни свой минус. Или подленько поставил и посмеиваешься в кулачок?
Мне кажется, Вы несколько неадекватны. Минус означает, что человек с Вами не согласен. Минус для того и существует, чтобы кратко выразить свое несогласие и вовсе не подразумевает развернутного пояснения. А вот приравнивая выражение несогласия с Вашей точкой зрения к подлости, Вы оскорбляете участников форума и, таким образом, нарушаете правила. Советую в дальнейшем следить за своими словами.
... << RSDN@Home 1.2.0 alpha rev. 721>>
'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
Здравствуйте, _ks_, Вы писали:
__>Кто впервые придумал проперти (это которые { get; set; }) ?
__>Просто у меня такое ощущение, что в C# оно появилось не первым. Обычно MS берёт идеи у других. Неужели такую удобную штуку они придумали сами?
И что же такого хорошего в этих пропетях? По моему так без них только лучше.
Здравствуйте, _d_m_, Вы писали: ___>Нда? Ну в таком случае — тебе прямая дорога в церковь. Я с этой мыслью не первый, а лишь согласен с Рихтером. Слышал про такого?
У Рихтера, имхо, какие-то личные проблемы с шарпом и дотнетом. Он в своей книге дает много откровенно бредовых рекомендаций. В целом, они выглядят как рассуждения престарелой монашки о сексе. Я лично не могу поверить, что от сходства синтаксиса проперти и поля могла возникнуть хоть на полпальца серъезная проблема. Что, кто-то хоть раз предположил, что Array.Length — это поле? Или от неверного предположения пострадали сотни невинных? Все эти рассказы про то, что код вида A+=1; вдруг имеет сложность O(N^6), "а мы не знали" — это ламерство вопиющее. Если ваше подсознание нашептывает, что A+=1 выполняется за константное время — сделайте вашему подсознанию апгрейд.
Еще он предлагал чтобы реализация object.Equals всегда возвращала true. Так, дескать, не будет разницы при перегрузке Equals, от какого класса мы наследуемся. Реальный бред — в дизни перегрузка Equals встречается очень редко, и она требует высокой квалификации. Иначе можно наделать чудных граблей. А вот рекомендация Рихтера махом привела бы к тому, что у всех экземпляров любого ссылочного типа был бы одинаковый хэш-код. И Equals приходилось бы перегружать на каждый чих. В общем, тяжелая наркомания налицо.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
___> MyClass c = new MyClass();
___> int d = c.I; // то, что здесь меняется состояние объекта "c" уж очень неочевидно
___> int e = c.get_I();
___>
По-моему, в обоих случаях одинаково неочевидно.
What a piece of work is a man! how noble in reason! how infinite in faculty! in form and moving how express and admirable! in action how like an angel! in apprehension how like a god! the beauty of the world! the paragon of animals!
Здравствуйте, Klapaucius, Вы писали:
K>Здравствуйте, _d_m_, Вы писали:
___>>Closer — поясни свой минус. Или подленько поставил и посмеиваешься в кулачок?
K>Мне кажется, Вы несколько неадекватны. Минус означает, что человек с Вами не согласен. Минус для того и существует, чтобы кратко выразить свое несогласие и вовсе не подразумевает развернутного пояснения.
Несогласен в чем? Несогласен почему? Насколько я знаю, здесь принято минусы аргументировать.
K>А вот приравнивая выражение несогласия с Вашей точкой зрения к подлости, Вы оскорбляете участников форума и, таким образом, нарушаете правила. Советую в дальнейшем следить за своими словами.
Здравствуйте, iZEN, Вы писали:
ZEN>Вот к чему приводит отсутствие checked-exceptions -- к наплевательскому отношению к коду, выполняющемуся к тому времени уже у клиента.
А присутствие к такому геморрою, что лучше бы их не было.
Здравствуйте, konsoletyper, Вы писали:
K>Хм, а вообще нужно ли перегружать Equals и GetHashCode у классов с reference-type семантикой?
У них — нет.
Но в жизни классы с value-type семантикой встречаются достаточно часто. Я, кстати, до сих пор не знаю, как ими правильно пользоваться.
Во мне крепнет убеждение, что value-type семантика однозначно требует immutability, иначе начинаются чудные спецэффекты. Посудите сами: Equals придуман так, что если два объекта в какой-то момент времени эквивалентны, то так будет и навсегда в будущем. На этом, в частности, построены все коллекции, которые вообще используют Equals. Из этого непосредственно следует, что если Equals строится на состоянии объекта, то это состояние нельзя изменять. В свете этого, мне вообше непонятно, зачем в дотнете разрешили сочетать перегрузку Equals/GetHashCode для изменяемых объектов.
Хэш-код — это всего лишь приятное дополнение к методу Equals, более грубое разбиение на классы эквивалентности. K>Кстати, а как работает object.GetHashCode()? Я так понимаю, он жёстко привязывается к объекту. Т.е. должно быть какое-то спец. поле у каждого объекта. Но, видимо, это не так...
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>...В свете этого, мне вообше непонятно, зачем в дотнете разрешили сочетать перегрузку Equals/GetHashCode для изменяемых объектов.
Дык в дотнете нет (на мой взгляд, напрасно) понятия неизменяемый тип. Неизменяемые объекты делаются паттерном. Это значит, что рантайм или компилятор ни ухом, ни рылом не знает о том, что объекты некоего типа являются неизменяемыми.
Меж тем введние подобного класса объектов (типов, точнее) было бы очень правильным решением (особенно в виду увеличения функциональщины в мэйнстриме). Такие объекты не только могли бы контролироваться рантаймом и компиляторами, но и могли бы позволить повысить производительность рантайма. Ведь GC с ними мог бы работать по другому. Они не требуют райт-барьена и могут жить в отдельной (более простой и эффективной) куче.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, BulatZiganshin, Вы писали:
C>>Дело в том, что, по идее, отношение эквивалентности должно быть рефлексивным, симметричным и транзитивным. Разные типы выбрасываемых исключений симметричность нарушают.
BZ>исключения не относятся к возвращаемым значениям. это аналогично бесконечности или неопределённости, от которых тружно ожидать выполнения матсвойств
Здравствуйте, _FRED_, Вы писали:
_FR>Можно: через "ручную" реализацию посредством EventHandlerList, например.
Знаешь в чем прелесть immutable объектов? В том, что они не создают побочных эффектов. Т.е. immutable объект можно передать куда угодно, не боясь что сторонний код чего то там поменяет. Если же мы позводим что то внутри менять, не важно как оно там организовано на самом деле, то состояние можно будет сменить.
Насколько я понял, здесь поднялся вопрос о целесообразности ИСПОЛЬЗОВАНИЯ свойств, а не о удобствах их определения. Ведь определяем мы лишь раз, а юзать можем сотню раз. Если бы программеры использовали методы для доступа к членам, то думаю так же бы появилась констукция вида:
private int m_filed {GetMethodName, SetMethodName};
Я хочу сказать, что AVK>
AVK>public int NetworkID
AVK>{ get; set; }
AVK>
является следствием, а не причиной использования свойств.
Одно из преимуществ propreties -- это связность getter-а и setter-а на уровне метаданных с введением новой, вполне естественной сущности. Возможность писать ABC, а не get_ABC(), set_ABC() -- это не более, чем приятный синтаксический сахар.
___>А семантика полей и проперти совпадают. Только в случае проперти можно реально огрести. Типа исключений, неочевидных изменений состояния объекта и прочего. К Рихтеру.
Все это примеры неудачного дизайна и использования properties не по назначению.
Здравствуйте, _d_m_, Вы писали: ___>Он не утверждает, что надо для всех объектов надо переопределять Equals.
Еще как утверждает. ___> Он рассуждает о том, как надо было бы Microsoft это сделать для Object и если уж надо переопределять Equals, то как.
Если бы микрософт последовала бы его совету, то перегрухать пришось бы в обязательном порядке для каждого наследника Object. Просто потому, что даже поиск в List<T> сделан через Equals, а неперегруженный Equals возвращал бы true для любой пары однотипных объектов. Это что, как-то очень неочевидно?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, _d_m_, Вы писали:
___>Здравствуйте, _ks_, Вы писали:
__>>Кто впервые придумал проперти (это которые { get; set; }) ?
__>>Просто у меня такое ощущение, что в C# оно появилось не первым. Обычно MS берёт идеи у других. Неужели такую удобную штуку они придумали сами?
___>И что же такого хорошего в этих пропетях? По моему так без них только лучше.
ZEN>>Категорически согласен. ZEN>>Кстати, в JavaBeans сделано прозрачнее, но доктрина "свойств" отвратительна (пришла в JavaBeans из ActiveX) и порождает массу ненужного кода -- часто огромный список финальных методов get|is/set с простым получением/присваиванием значений полей, которые никогда не будут перегружены. Такова плата за "инкапсюляцию".
___>Ну вот, мы с Рихтером теперь не одни
___>Резюме. ___>Вобщем аргументы оппонентов сводятся к следующему: ___>Ну да в свойствах могут быть косяки, но только если их неправильно применять. Но мы их всегда правильно применяем. И давайте же будем оптимистами, что и другие программисты их применяют правильно. Но если они их применяют неправильно, то это сразу видно и не стОит использовать их сборки. Но на всякий случай, от сборок третьих фирм всегда надо ждать сюрпризов при обращении со свойствами. ___>С последним предложением, в принципе, я согласен.
Браво!!!
А теперь замените выделеное слово на любое другое (например "функциях", или "классах") и опять же получите совершенно верное утверждение!
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, _d_m_, Вы писали: ___>>Он не утверждает, что надо для всех объектов надо переопределять Equals. S>Еще как утверждает. ___>> Он рассуждает о том, как надо было бы Microsoft это сделать для Object и если уж надо переопределять Equals, то как. S>Если бы микрософт последовала бы его совету, то перегрухать пришось бы в обязательном порядке для каждого наследника Object. Просто потому, что даже поиск в List<T> сделан через Equals, а неперегруженный Equals возвращал бы true для любой пары однотипных объектов. Это что, как-то очень неочевидно?
Для меня очевидно как раз другое. Это то, что поиск в List<T> должен использовать не Equals, а ReferenceEquals. Да и для чего существует тогда два метода, которые на самом деле одно и тоже?
MSDN:
Object.Equals — Determines whether the specified Object is equal to the current Object. (Тогда какого хрена он работает как ReferenceEquals?)
Object.ReferenceEquals — Determines whether the specified Object instances are the same instance.
Ну так где бред и тяжелая наркомания? Может стоит сначала разобраться, а потом вешать ярлыки?
Здравствуйте, Andrei N.Sobchuck, Вы писали:
ANS>... что там пишут то?
...
4. Не используйте публичные поля, вместо них следует использовать свойства.
5. Используйте свойства, вместо Get/Set методов.
6. Используйте методы, если выполняемая операция является преобразованием, обладает побочными эффектами, долго выполняется или если важен порядок выполнения операций.
7. Свойство не должно менять своего значение от вызова к вызову, если состояние объекта не изменяется. Если результат при новом вызове может быть другим при том же состоянии объекта, используйте метод.
8. Не используйте свойства «только для записи». Потребность в таком свойстве может быть признаком плохого проектирования.
....
Здравствуйте, _ks_, Вы писали:
__>Кто впервые придумал проперти (это которые { get; set; }) ? __>Просто у меня такое ощущение, что в C# оно появилось не первым. Обычно MS берёт идеи у других. Неужели такую удобную штуку они придумали сами?
Я думаю, тут все дело в Хейлсберге, который делал и Delphi и C#.
См. интервью здесь.
People have suggested that C# is sort of Delphi v2.0. Do you think that is a fair assessment? Is a lot of like breaking in the component model as part of the language, is a lot of that experience from having done some of the stuff with Delphi at Borland?
Well, there is no doubt that there is heritage from Delphi. Delphi has properties, Delphi has events and so forth, and if I have to go do it again, I still think they are useful concepts. So I would put into the next one too, if there was a next one. I think you learn from what you've done. You learn from your past mistakes, you know what worked and what didn't, and you keep the stuff that worked, and then you get rid of the stuff that didn't. Those are definitely things that worked and I think they are some of the things that made Delphi a great product.
Здравствуйте, ryf, Вы писали:
ryf>Порше 911 — г@##о, на нем больше двух мешков картошки с дачи не увезешь. Исходя из такого подхода, любый инструмент можно испоганить при использовании не по назначению, это не говорит от том, что инструмент кривой, это говорит лишь о криворукости юзера.
Насчет Порше.
Если мы решаем задачу по перевозу картошки или навоза, то нам конечно, Порше не подойдет. Но я думаю здесь вопрос несколько в другой плоскости... Вот аналогия: не могу найти, но читал где-то в инете. В советские времена принес дед в ремонт радиотранслятор — это такой динамик с вилкой втыкаемой в низковольтную радиосеть. Но вилка была как на питание 220 В, но естествено транслятор для этого не предназначался. Отремонтировали, приходит дед забирать: "Ну что, проверяем." Оп вилку в сеть 220 — дым — транслятор сгорел. "Извините, все починим — приходите через N дней". А там несколько сменщиков и так несколько раз горел этот транслятор.
Так вот, вилка на 220 несла семантику включение в силовую розетку напряжением 220, но для этого не предназначалась.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, _d_m_, Вы писали: ___>>Я специально перечитал не моргая параграф "Тождество и равенство", где подробно обсуждается Object.Equals() и Object.GetHashCode() и не нашел даже намека на: "чтобы реализация object.Equals всегда возвращала true". Где это написано, если не секрет? Или голоса в голове подсказали? Или, как мне тут уже объяснили, это какой-то другой Рихтер с которым я перешептываюсь нежно на ушко. S>К моему прискорбию, это в нем вычитал не я — мне показывали фрагмент из ебука во время спора на эту тему. Вот поклонник Рихтера выйдет из отпуска — я поточнее посмотрю, откуда дровишки.
Еще один "не читал, но осуждаю".
2 all: Уж я не знаю, как кто книги читает, но — Рихтер, CLR via C#, Питер, 2007, стр. 138-139:
У типа System.Object есть виртуальный метод Equals, который возвращает true для двух "равных" объектов. Вот реализация метода Equals для Object:
public class Object {
public virtual Boolean Equals(Object obj) {
if (this == obj) return true;
return false;
}
}
... Иначе говоря, оказывается, что стандартная реализация метода метода Equals типа Object реализует проверку на тождество, а не на равенство.
Как видите, оказалось, что приведнная выше стандартная реализация не годится: нужно переопределить Equals и написать его собственную реализацию.
Вот как нужно это делать:
1. Если аргумент obj равен null, вернуть false.
2. Если obj и this ссылаются на объекты разного типа — вернуть false. 3. Сравнить все определнные в типе экземплярные поля объектов obj и this. Если хотя бы одна пара полей не совпадает — вернуть false.
4. Вызвать метод Equals базового класса, чтобы сравнить определнные в нем поля. Если метод базового класса вернул false, тоже вернуть false, иначе вернуть true.
Поэтому Microsoft должна была реализовать метод Equals типа Object так:
public class Object {
public virtual Boolean Equals(Object obj) {
if( obj == null ) return false;
if( this.GetType() != obj.GetType() ) return false;
// Т.к. в System.Object не определены поля, следует считать, что поля равныreturn true;
}
}
Здравствуйте, _d_m_, Вы писали: ___>Для меня очевидно как раз другое. Это то, что поиск в List<T> должен использовать не Equals, а ReferenceEquals.
Щас прям!
И как тогда будет работать List<int>?
___>Ну так где бред и тяжелая наркомания? Может стоит сначала разобраться, а потом вешать ярлыки?
Ок, давайте разберемся. Когда мы встречаем непонимание разницы между идентичностью (ReferenceEquals) и эквивалентностью (Equals) у новичка — это недостаток знаний. Когда такое непонимание встречается у профессионала — это бред и тяжелая наркомания.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, _d_m_, Вы писали:
L>>Имхо, чтобы избежать перечисленного нет необходимости отказываться от свойств. Достаточно всего лишь запретить не-приватные поля.
___>Но это совсем ничего не изменит.
Изменит все. Ни один пункт из аргументации работать не будет.
Здравствуйте, iZEN, Вы писали:
ZEN>Этот "геморрой" проверяется компилятором на этапе компиляции (или сразу в редакторе кода)
Угу, то-то большинство явистов, оптом предпочитают декларировать одно большое исключение на все случаи жизни, чтобы компилятор лишний раз не тревожил. Похоже классический пример, когда лекарство хуже болезни.
Здравствуйте, Sinclair, Вы писали:
S>Отлично. В принципе, это наверное бы даже сработало, но тогда бы коллекции пришлось бы ограничить констреинтом на реализацию этого интерфейса.
Так было бы гораздо лучше, чем то, что сейчас, когда во время выполнения можно огрести.
И вообще, коллекции в BCL спроектированы довольно похабно (один IList<T> чего стоит).
Здравствуйте, VladD2, Вы писали:
VD>Такие объекты не только могли бы контролироваться рантаймом и компиляторами, но и могли бы позволить повысить производительность рантайма. Ведь GC с ними мог бы работать по другому. Они не требуют райт-барьена и могут жить в отдельной (более простой и эффективной) куче.
Интересно, а эти самые неизменяемые объекты могут держать ссылки на изменяемые объекты?
Здравствуйте, _FRED_, Вы писали:
_FR>На самом деле предложение VladD2 запретить неизменяемым объектам ссылаться (иметь как поля) изменяемые меня удивила. Выходит, неизменяемые объекты не могут содержать событий, например. То есть резко ограничены по функциональности по сравнению с обычными типами (классами), зато выгодны с точки зрения потребления ресурсов, например. И я пока не вижу, где была бы польза от использования таких объектов
А зачем неизменяемому объекту события? Она же получил свое состояние раз и на всегда. Зачем кого-то оповещать? В прочем, если надо, то нет проблем передатьс ссылки на методы обратной свизи в констурктор.
Есть туча мест где было бы выгодно иметь неизменяемые объекты. И контроль во время компиляции в купе с уменьшением цены владения объектом никому бы не помешал бы. Примеры таких объектов у нас перед глазами: связанные списки (очень часто используются в ФП), строки, бинарные деревья. Неизменяемыми можно было бы сделать шрифты, кисти и другие информационные объекты.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, mogadanez, Вы писали:
M>не попробуешь, не узнаешь, мы попробовали — нам понравилось. M>через _ логические части имени разделяются лучше чем при заглавной букве.
ИМХО без разници.
Но вы отступили от общепринятого стандарта что есть плохо.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, _FRED_, Вы писали:
_FR>На самом деле предложение VladD2 запретить неизменяемым объектам ссылаться (иметь как поля) изменяемые меня удивила. Выходит, неизменяемые объекты не могут содержать событий, например. То есть резко ограничены по функциональности по сравнению с обычными типами (классами), зато выгодны с точки зрения потребления ресурсов, например. И я пока не вижу, где была бы польза от использования таких объектов
Ты не пользуешься строками в своих программах?
... << RSDN@Home 1.2.0 alpha rev. 717>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, konsoletyper, Вы писали:
K>Т.е. должно быть какое-то спец. поле у каждого объекта. Но, видимо, это не так...
Есть такое поле, sync block index называется. Оно же заодно связано с объектом синхронизации, который потенциально может быть заведен для любого экземпляра.
Здравствуйте, _ks_, Вы писали:
N>>И к тому же глючно. Я как-то приводил пример, когда сравнение структуры с собой дает false. __>Кинтесь ссылочкой, плиз. Очень интересно!
... Mab>Здравствуйте, _d_m_, Вы писали:
Mab>Одно из преимуществ propreties -- это связность getter-а и setter-а на уровне метаданных с введением новой, вполне естественной сущности. Возможность писать ABC, а не get_ABC(), set_ABC() -- это не более, чем приятный синтаксический сахар.
...
Еще удобно их использовать при привязке полей объектов к форме.
Разметил атрибутами и при построении формы, автоматом идет привязка полей объектов к контролам на форме, и не надо писать тупой код по установке и получению значений контролов и пропихивания их в объект.
Здравствуйте, Andrbig, Вы писали:
A>Если твой Рихтер сказал это тебе нежно на ушко — про такого не знаю. А если это тот, который автор книг — слышал и хочется увидеть цитаты.
CLR via C#, Издательство "Питер", 2007 г., стр 208.
Лично мне свойства не нравятся, и я был бы рад, если бы их поддержку убрали из Microsoft .NET Framework и сопутствующих языков программирования.
Здравствуйте, AK85, Вы писали:
AK>Здравствуйте, _d_m_, Вы писали:
AK>Я Рихтера помню еще с... Win NT 3.51. Рихтер это мужик с большой буквы — я о его книгах по программированию. И опыт у него огромный — не как "у нас с вами".
AK>Последняя книга (CLR via C#) имхо неудачная.
Здравствуйте, _ks_, Вы писали:
___>>И, кстати, поводу опыта Рихтера в C# — я не сказал, что его у него мало: "А PowerCollections..." это что точно знаю я. Конечно, ты можешь не доверять Рихтеру — это конечно дело твое. Но конкретно с чем ты не согласен?
__>С тем что перечисленные им проблемы проблемами не являются.
Ну тогда: "не приведи господь поддерживать твой код" добавлю от себя: и использовать твои сборки.
___>>А сказать просто, что Рихтер ламер в С# (при этом не читая его его книг) — это не аргумент и даже как-то смешно.
__>Там (у меня в предложении) стоИт ИМХО. И это ИМХО твёрдое.
Ну я рад, что у тебя ИМХО так твердо стоИт.
___>>PS: "Не читал, но осуждаю" (С) Жванецкий
__>Не читал, но сделанные им выводы меня обескураживают.
_
___>Ну вот чуток из ___>Джеффри Рихтер, "CLR via C#": ___>
___>Лично мне свойства не нравятся, и я был бы рад, если бы их поддержку убрали из Microsoft .NET Framework и сопутсвующих языков программирования. Причина в том, что свойства выглядят как поля, на самом деле являясь методами. Это порождает массу заблуждений и непонимания. Столкнувшись с кодом, обращающимся к полю, разработчик предполагает наличие массы условий, которые не всегда верны, если речь идет о свойстве.
___>...
___>- метод свойства может привести к исключению, а при доступе к полям исключений не бывает;
___>...
___>- метод свойства может выполнятся довольно долго, а доступ к полям выполняется моментально. Часто свойства используют для синхронизации потоков, но это может привести к приостановке потока на неопределенное время — поэтому свойства не следует использовать для этих целей — в такой ситуации лучше задействовать метод. Кроме, того если предусмотрен удаленный доступ к классу (например, если он наследует System.MarshalByRefObject), вызов метода свойства выполнится очень медленно, поэтому предпочтение следует отдать методу. Я считаю, что в классах, производных от MarshalByRefObject, никогда не следует использовать свойства;
___>- при вызове несколько ряд подряд метод свойства может возвращать разные значения, а поле возвращает одно и тоже значение. В классе System.DateTime есть неизменяемое свойство Now ...
___>- метод свойства может создавать наблюдаемые стороние эффекты, а при доступе к полю это невозможно...
___>- методу свойства может требоваться дополнительная память или ссылка на объект, не являющаяся частью состояния объекта, поэтому изменение возвращаемого объекта никак не сказывается на исходном объекте; при запросе поля всегда возвращается ссылка на объект, который гарантировано относиться к состоянию исходного объекта. Свойство, возвращающее копию, — источник замешательства для разработчиков, причем это поведение часто забывают упомянуть в документации.
___>...
___>PS: Ну так чей код "не приведи господь" лучше поддерживать?
Порше 911 — г@##о, на нем больше двух мешков картошки с дачи не увезешь. Исходя из такого подхода, любый инструмент можно испоганить при использовании не по назначению, это не говорит от том, что инструмент кривой, это говорит лишь о криворукости юзера.
Здравствуйте, _ks_, Вы писали:
__>>>Имхо, все перечисленные пункты — не проблема. Совсем не проблема. Так говорит мне опыт. __>>>Единственное что реально мешает это — Причина в том, что свойства выглядят как поля, на самом деле являясь методами. __>>>Но этого мы избегаем, называя переменные с маленькой буквы, а свойства с заглавной.
___>>Ну отлично. А Вася Пупкин так не делает. А мы вот используем его сборки в своих проектах.
__>Да, здесь начинаются "проблемы". __>Интелисенс всегда покажет свойство это или переменная.
А что такое интелисенс и какое отношение оно имеет к языку C#?
PS: Я знаю, что такое интелисенс и регулярно им пользуюсь (а то минус мне поставит . Но не обязан знать и пользоваться.
Здравствуйте, _ks_, Вы писали:
___>>О чем сообщение было — не понял, но минус на всякий случай... ммм... зафигачил. Ага, "не читал, но осуждаю"
__>Аааа... минус. Я его поставил сначала, потому что мне показались что Ваши слова противоречивы (и до сих пор кажутся). А потом еще раз подумал, а потом еще раз, а потом еще раз, а потом перестал работать и написал ответ.
Ну я обычно сначал думаю, а потом оценки ставлю. Ну, да ладно, у нас с Рихтером все никак у людей
Здравствуйте, _ks_, Вы писали:
__>Рвз уж мы переехали в Философию программирования, то спрошу начитанную общественность вот что.
__>Какая практическая польза от здесь сахара?
Здравствуйте, _d_m_, Вы писали:
___>Ага, я решил в своем проекте использовать сборку Васи Пупкина. Где гарантия, что он их использовал по назначению? Уж если даже в самой FCL они не всегда по назначению. Это как с управлением памятью в C/C++ — надо просто ее всегда ее освобождать. Но... не всегда получалось — и память текла. И тогда подумали и сделали .Net и в нем GC. Чуствуешь взаимосвязь?
Думаю, что Васю Пупкина и GC не остановит. ИМХО возможность для низкоквалифицированных кадров устроить неприятность не должна быть ключевым аргументом за или против. Зачем нам равняться на команды посредственностей? Уровень дуракоустойчивости должен быть разумным.
Бывают конструкции, которые позволяют получить проблемы на ровном месте всего лишь из-за невнимательности или банальной опечатки. Такие неприятности могут случится с любым разработчиком. Использование таких конструкций однозначно надо сильно ограничивать.
Исопльзование же свойств не по назначению будет сознательно допущенной ошибкой дизайна, которую должен обранужить первый же code review. Кроме того, я сходу не могу вспомнить в своей практике случаев, когда при грамотном проектировании свойства давали бы труднодиагностируемые и трудноуловимые ошибки.
Так что с моей точки зрения плюсы сильно перевешивают минусы.
Здравствуйте, _d_m_, Вы писали:
___>Здравствуйте, _FRED_, Вы писали:
_FR>>Здравствуйте, _d_m_, Вы писали:
___>>>Нда? Ну в таком случае — тебе прямая дорога в церковь. Я с этой мыслью не первый, а лишь согласен с Рихтером. Слышал про такого?
_FR>>Ты бы сначала задался вопросом, что именно не понравилось Рихтеру в свойствах и уже только потом решал, соглашаться с ним или нет.
_FR>>Ты вот на каких основаниях с ним согласен?
___>Ну вот чуток из ___>Джеффри Рихтер, "CLR via C#": ___>
___>Лично мне свойства не нравятся, и я был бы рад, если бы их поддержку убрали из Microsoft .NET Framework и сопутсвующих языков программирования. Причина в том, что свойства выглядят как поля, на самом деле являясь методами. Это порождает массу заблуждений и непонимания. Столкнувшись с кодом, обращающимся к полю, разработчик предполагает наличие массы условий, которые не всегда верны, если речь идет о свойстве.
___>...
___>- метод свойства может привести к исключению, а при доступе к полям исключений не бывает;
___>...
___>- метод свойства может выполнятся довольно долго, а доступ к полям выполняется моментально. Часто свойства используют для синхронизации потоков, но это может привести к приостановке потока на неопределенное время — поэтому свойства не следует использовать для этих целей — в такой ситуации лучше задействовать метод. Кроме, того если предусмотрен удаленный доступ к классу (например, если он наследует System.MarshalByRefObject), вызов метода свойства выполнится очень медленно, поэтому предпочтение следует отдать методу. Я считаю, что в классах, производных от MarshalByRefObject, никогда не следует использовать свойства;
___>- при вызове несколько ряд подряд метод свойства может возвращать разные значения, а поле возвращает одно и тоже значение. В классе System.DateTime есть неизменяемое свойство Now ...
___>- метод свойства может создавать наблюдаемые стороние эффекты, а при доступе к полю это невозможно...
___>- методу свойства может требоваться дополнительная память или ссылка на объект, не являющаяся частью состояния объекта, поэтому изменение возвращаемого объекта никак не сказывается на исходном объекте; при запросе поля всегда возвращается ссылка на объект, который гарантировано относиться к состоянию исходного объекта. Свойство, возвращающее копию, — источник замешательства для разработчиков, причем это поведение часто забывают упомянуть в документации.
___>...
Категорически согласен.
Кстати, в JavaBeans сделано прозрачнее, но доктрина "свойств" отвратительна (пришла в JavaBeans из ActiveX) и порождает массу ненужного кода -- часто огромный список финальных методов get|is/set с простым получением/присваиванием значений полей, которые никогда не будут перегружены. Такова плата за "инкапсюляцию".
Здравствуйте, iZEN, Вы писали:
ZEN>Категорически согласен. ZEN>Кстати, в JavaBeans сделано прозрачнее, но доктрина "свойств" отвратительна (пришла в JavaBeans из ActiveX) и порождает массу ненужного кода -- часто огромный список финальных методов get|is/set с простым получением/присваиванием значений полей, которые никогда не будут перегружены. Такова плата за "инкапсюляцию".
Ну вот, мы с Рихтером теперь не одни
Резюме.
Вобщем аргументы оппонентов сводятся к следующему:
Ну да в свойствах могут быть косяки, но только если их неправильно применять. Но мы их всегда правильно применяем. И давайте же будем оптимистами, что и другие программисты их применяют правильно. Но если они их применяют неправильно, то это сразу видно и не стОит использовать их сборки. Но на всякий случай, от сборок третьих фирм всегда надо ждать сюрпризов при обращении со свойствами.
С последним предложением, в принципе, я согласен.
IB,
ZEN>>Этот "геморрой" проверяется компилятором на этапе компиляции (или сразу в редакторе кода) IB>Угу, то-то большинство явистов, оптом предпочитают декларировать одно большое исключение на все случаи жизни, чтобы компилятор лишний раз не тревожил. Похоже классический пример, когда лекарство хуже болезни.
Здравствуйте, _d_m_, Вы писали:
___>Еще один "не читал, но осуждаю".
[skip]
Ну вот, прочитали. Теперь осуждеаем квалифицированно. Рихтер в своих рассуждениях забывает тот факт, что вообще не для всех объектов (причём далеко не для всех) есть смысл переопределять Equals. В ООП объекты обладают identity, и сравнивать их, соотвественно, имеет смысл только по этому identity. Equals был введён для грубой эмуляции ФП.
Здравствуйте, Cyberax, Вы писали:
C>>>В этом случае лучше кинуть NullReferenceException — чтобы сохранить C>>>коммутативность. N>>Существует мнение, что вручную бросать NullReferenceException — строго неправильно. C>Почему?
Потому что для этой цели существует ArgumentNullException.
C>>>String a="aadfafasf";
C>>>String b=null;
C>>>b.equals(a); //<--- NullPointerException
C>>>a.equals(b); //<--- А почему тогда тут не оно?!
C>>>
N>>Потому что в последней строке я не пытаюсь вызвать метод у null-ссылки. C>Дело в том, что, по идее, отношение эквивалентности должно быть рефлексивным, симметричным и транзитивным. Разные типы выбрасываемых исключений симметричность нарушают.
Тут я мог бы возразить, что в первой строке до вызова метода, реализующего отношение эквивалентности, дело не доходит.
Здравствуйте, Cyberax, Вы писали:
C>В этом случае лучше кинуть NullReferenceException — чтобы сохранить C>коммутативность.
А лучше тупо определить operator== и в нём, после проверки object.ReferenceEquals(a, b), сделать такующе проверку на object.ReferenceEquals(a, null) и object.ReferenceEquals(b, null) (если вообще в данном случае null имеет смысл, иначе, кидать исключения). При этом Equals тупо возвращает результат сравнения ==, естественно, перед проверкой типа.
C>Ну и тупо возвращать 'true' — это тоже плохо. Так как срубает C>возможность класть объекты в hash-контейнеры.
C>Дело в том, что, по идее, отношение эквивалентности должно быть рефлексивным, симметричным и транзитивным. Разные типы выбрасываемых исключений симметричность нарушают.
исключения не относятся к возвращаемым значениям. это аналогично бесконечности или неопределённости, от которых тружно ожидать выполнения матсвойств
Здравствуйте, _d_m_, Вы писали:
___>По хорошему, чтобы метод Object.Equals работал для наследников корректно — надо использовать отражение для сравнения значений полей.
Ха! Оно уже используется для структур и там всё совсем не просто и даже не очевидно.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
___>>По хорошему, чтобы метод Object.Equals работал для наследников корректно — надо использовать отражение для сравнения значений полей.
_FR>Ха! Оно уже используется для структур и там всё совсем не просто и даже не очевидно.
И к тому же глючно. Я как-то приводил пример, когда сравнение структуры с собой дает false.
C>>>Дело в том, что, по идее, отношение эквивалентности должно быть рефлексивным, симметричным и транзитивным. Разные типы выбрасываемых исключений симметричность нарушают.
BZ>>исключения не относятся к возвращаемым значениям. это аналогично бесконечности или неопределённости, от которых тружно ожидать выполнения матсвойств
__>Ахренеть! Вот это аналогия...
это не аналогия. водные данные выходят за обалсть определения функции, и идёт чисто технический сигналлинг об этом для упрощения отладки. DivideByZero — один из типичных exceptions
__>Бросай курить.
Здравствуйте, Sinclair, Вы писали:
S>Рихтер предлагает по умолчанию считать любые два экземпляра этого класса эквивалентными. Надо полагать, от большого ума.
Синклер, все нормально, я с тобой согласен, но не надо про "большой ум" и т.п. Несколько раздражает.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Sinclair, Вы писали:
_FR>>Это аналог const-методов в С++? То есть методы декларируют, что неизменяют внутреннего состояния объекта? А должен ли это проверять компилятор? S>Нет, не компилятор, а верификатор.
То есть проверяться это будет в рантайме Под "компилятором" я имел в виду compile-time, то есть процесс, происходящий во время компиляции
На самом деле предложение VladD2 запретить неизменяемым объектам ссылаться (иметь как поля) изменяемые меня удивила. Выходит, неизменяемые объекты не могут содержать событий, например. То есть резко ограничены по функциональности по сравнению с обычными типами (классами), зато выгодны с точки зрения потребления ресурсов, например. И я пока не вижу, где была бы польза от использования таких объектов
Мне казалось, что неизменяемый объект должен иметь неизменяемые (readonly в терминах шарпа) поля, а поля эти могут быть так же как неизменяемыми, так и изменяемыми.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Мне казалось, что для immuta-бильности достаточно иметь все поля readonly (в сегодняшнем смысле, то есть константные ссылки, а не ссылки на константы) — ведь именно тогда объект является неизменяемым? А вот являются ли неизменяемыми типы этих полей — их личное дело. Ведь при изменении внутренних данных своего поля объект не меняется. Или я не прав и что-то не знаю\не понимаю?
Если под иммутабельным объектом понимают ValueObject, то по идее неприватные свойства тоже должны быть иммутабельны. Например, представь значение типа Person со свойством Name мутабельного типа StringBuilder. По моему, если меняется свойство, то и сам объект тоже меняется (в том смысле, что это уже не значение).
Здравствуйте, AndrewVK, Вы писали:
AVK>Знаешь в чем прелесть immutable объектов? В том, что они не создают побочных эффектов. Т.е. immutable объект можно передать куда угодно, не боясь что сторонний код чего то там поменяет. Если же мы позводим что то внутри менять, не важно как оно там организовано на самом деле, то состояние можно будет сменить.
Ага! Правильно ли я понянял вас с IT, что эти самые immutable-объекты, которых я не понимаю: эмуляция типов с семантикой значения? Вернее даже не "эмуляция", а новый их аттрибут, который сможет помочь рантайму более производительно обрабытывать эти типы?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, EvilChild, Вы писали:
EC>Например есть IEnumerable<string>, надо вернуть IEnumerable<object>. EC>Тупо return значение типа IEnumerable<string> из функции с типом возвращаемого значения IEnumerable<object> не прокатит. EC>Вот yield return единственный известный мне выход.
Достаточно один раз написать.
IEnumerable<T> Cast<T>(IEnumerable src) where T : class
{
foreach (object item in src)
yield return (T)item;
// Вариант:
// T typedItem = item as T;
// if (item != null)
// yield return (T)item;
}
В linq2objects что то подобное есть ввиде extension method.
А вобще необходимость подобных финтов, да еще и в большом количестве это повод задуматься.
Здравствуйте, AndrewVK, Вы писали:
AVK>А если присмотреться повнимательнее?
Вот, что мне нужно было:
private static IEnumerable<TOutput> Cast<TInput, TOutput>(IEnumerable<TInput> coll)
where TInput : TOutput
{
foreach (TInput item in coll)
yield return (TOutput)item;
}
Вот пример использования:
IEnumerable<object> test = Cast<string, object>(new string[] {"1", "2"});
AVK>О дизайне.
Поясню что я имел в виду.
Есть readonly интерфейс IReadonly и класс его реализующий SomeClass : IReadonly.
SomeClass объявлен приватно в другом классе SomeAggregate.
Клиенты класса SomeAggregate знают только об IReadonly.
В экземпляре класса SomeAggregate есть контейнер экземпляров типа SomeClass, который надо вернуть как IEnumerable<IReadonly>.
Именно для этого случая мне понадобилась ковариантность, причём она здесь совершенно безопасна.
Здравствуйте, _FRED_, Вы писали:
_FR>Так как IEnumerable<TInput> "унаследован" от IEnumerable, то версия AndrewVK "общее" и полностью покрывает твою. Проверь
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, mogadanez, Вы писали:
M>>>>плохо кому? WH>>>Тому кто с этим кодом будет работать.
M>>МЫ
_FR>Если вы не собираетесь менять состав команды на протяжении всей жизни проекта — то ладно, но таким мало кто может похвастать. В условиях же, когда "окружение" может меняться общие и единые стандарты — именно то средство, которое позволит изменениям "притереться" друг к другу с наименьшими проблемами. Во
_FR>Хотя, читать ваши исходники совсем не плохо, но это настолько отходит от общепринятых норм…
вот мнение человека об этом недавно пришедшего в команду. на момент поста — ~месяц
Здравствуйте, nikov, Вы писали:
N>Здравствуйте, _ks_, Вы писали:
__>>Кто впервые придумал проперти (это которые { get; set; }) ? __>>Просто у меня такое ощущение, что в C# оно появилось не первым. Обычно MS берёт идеи у других. Неужели такую удобную штуку они придумали сами?
N>Я думаю, тут все дело в Хейлсберге, который делал и Delphi и C#. N>См. интервью здесь.
А в разработке технологии COM он случайно участия не принимал? Там эти пропети уже давненько. Ж..ой чую — в COM из Васика пошло, а откуда там это чудо взялось — я не знаю.
Здравствуйте, _d_m_, Вы писали: ___>И что же такого хорошего в этих пропетях? По моему так без них только лучше.
Обоснуй. Плодить геттеры и сеттеры (как в Java)? Я конечно понимаю, что в современных IDE это не особая проблема (ассистенты и снипетты всякие), но, ИМХО, код более загроможденный.
Так
string networkID;
public int NetworkID
{
get { return this.networkId; }
set { this.networkId = value; }
}
удобнее чем
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
Здравствуйте, _d_m_, Вы писали:
___>Здравствуйте, _ks_, Вы писали:
__>>Кто впервые придумал проперти (это которые { get; set; }) ?
__>>Просто у меня такое ощущение, что в C# оно появилось не первым. Обычно MS берёт идеи у других. Неужели такую удобную штуку они придумали сами?
___>И что же такого хорошего в этих пропетях? По моему так без них только лучше.
Я думаю главное достоинство — возможность разграничения доступа, например паблик геттер и интернал сеттер. Ну и возможность выполнения дополнительного кода при обращении как с полями.
Здравствуйте, BlackHeretic, Вы писали:
BH>Здравствуйте, _d_m_, Вы писали:
___>>Здравствуйте, _ks_, Вы писали:
__>>>Кто впервые придумал проперти (это которые { get; set; }) ?
__>>>Просто у меня такое ощущение, что в C# оно появилось не первым. Обычно MS берёт идеи у других. Неужели такую удобную штуку они придумали сами?
___>>И что же такого хорошего в этих пропетях? По моему так без них только лучше.
BH>Не приведи господь поддерживать твой код
Нда? Ну в таком случае — тебе прямая дорога в церковь. Я с этой мыслью не первый, а лишь согласен с Рихтером. Слышал про такого?
Здравствуйте, Farsight, Вы писали:
F>Здравствуйте, _d_m_, Вы писали: ___>>И что же такого хорошего в этих пропетях? По моему так без них только лучше.
F>Обоснуй. Плодить геттеры и сеттеры (как в Java)? Я конечно понимаю, что в современных IDE это не особая проблема (ассистенты и снипетты всякие), но, ИМХО, код более загроможденный.
Чем он загромажденный? :
int networkID;
public int NetworkID
{
get { return this.networkId; }
set { this.networkId = value; }
}
То же самое, что и:
private int id;
public int getId() { return id; }
public void setId(int id) { this.id = id; }
А семантика полей и проперти совпадают. Только в случае проперти можно реально огрести. Типа исключений, неочевидных изменений состояния объекта и прочего. К Рихтеру.
Здравствуйте, _d_m_, Вы писали:
___>А семантика полей и проперти совпадают. Только в случае проперти можно реально огрести. Типа исключений, неочевидных изменений состояния объекта и прочего. К Рихтеру.
Ну это сказки. Посмотри в MSIL. Там компилятором генерируются те же геттеры и сеттеры. Это не более чем повышение комфорта при программировании.
Здравствуйте, _d_m_, Вы писали:
___>Здравствуйте, BlackHeretic, Вы писали:
BH>>Здравствуйте, _d_m_, Вы писали:
___>>>Здравствуйте, _ks_, Вы писали:
__>>>>Кто впервые придумал проперти (это которые { get; set; }) ?
__>>>>Просто у меня такое ощущение, что в C# оно появилось не первым. Обычно MS берёт идеи у других. Неужели такую удобную штуку они придумали сами?
___>>>И что же такого хорошего в этих пропетях? По моему так без них только лучше.
BH>>Не приведи господь поддерживать твой код
>Нда? Ну в таком случае — тебе прямая дорога в церковь. Я с этой мыслью не первый, а лишь согласен с Рихтером. Слышал про такого?
Если твой Рихтер сказал это тебе нежно на ушко — про такого не знаю. А если это тот, который автор книг — слышал и хочется увидеть цитаты.
Здравствуйте, _d_m_, Вы писали:
___>Нда? Ну в таком случае — тебе прямая дорога в церковь. Я с этой мыслью не первый, а лишь согласен с Рихтером. Слышал про такого?
Ты бы сначала задался вопросом, что именно не понравилось Рихтеру в свойствах и уже только потом решал, соглашаться с ним или нет.
Ты вот на каких основаниях с ним согласен?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Mab, Вы писали:
___>>А семантика полей и проперти совпадают. Только в случае проперти можно реально огрести. Типа исключений, неочевидных изменений состояния объекта и прочего. К Рихтеру. Mab>Все это примеры неудачного дизайна и использования properties не по назначению.
+1, я бы ещё запретил возможность объявить set-метод с более широкой областью видимости, чем get- к прочему сахару из C# 3.0. В принципе, то, что свойства можно использовать неправильно тогда, когда этого можно _безболезненно_ избежать, говорит не в их пользу
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, _d_m_, Вы писали:
___>>Нда? Ну в таком случае — тебе прямая дорога в церковь. Я с этой мыслью не первый, а лишь согласен с Рихтером. Слышал про такого?
_FR>Ты бы сначала задался вопросом, что именно не понравилось Рихтеру в свойствах и уже только потом решал, соглашаться с ним или нет.
_FR>Ты вот на каких основаниях с ним согласен?
Ну вот чуток из
Джеффри Рихтер, "CLR via C#":
Лично мне свойства не нравятся, и я был бы рад, если бы их поддержку убрали из Microsoft .NET Framework и сопутсвующих языков программирования. Причина в том, что свойства выглядят как поля, на самом деле являясь методами. Это порождает массу заблуждений и непонимания. Столкнувшись с кодом, обращающимся к полю, разработчик предполагает наличие массы условий, которые не всегда верны, если речь идет о свойстве.
...
— метод свойства может привести к исключению, а при доступе к полям исключений не бывает;
...
— метод свойства может выполнятся довольно долго, а доступ к полям выполняется моментально. Часто свойства используют для синхронизации потоков, но это может привести к приостановке потока на неопределенное время — поэтому свойства не следует использовать для этих целей — в такой ситуации лучше задействовать метод. Кроме, того если предусмотрен удаленный доступ к классу (например, если он наследует System.MarshalByRefObject), вызов метода свойства выполнится очень медленно, поэтому предпочтение следует отдать методу. Я считаю, что в классах, производных от MarshalByRefObject, никогда не следует использовать свойства;
— при вызове несколько ряд подряд метод свойства может возвращать разные значения, а поле возвращает одно и тоже значение. В классе System.DateTime есть неизменяемое свойство Now ...
— метод свойства может создавать наблюдаемые стороние эффекты, а при доступе к полю это невозможно...
— методу свойства может требоваться дополнительная память или ссылка на объект, не являющаяся частью состояния объекта, поэтому изменение возвращаемого объекта никак не сказывается на исходном объекте; при запросе поля всегда возвращается ссылка на объект, который гарантировано относиться к состоянию исходного объекта. Свойство, возвращающее копию, — источник замешательства для разработчиков, причем это поведение часто забывают упомянуть в документации.
...
PS: Ну так чей код "не приведи господь" лучше поддерживать?
Здравствуйте, AK85, Вы писали:
AK>Я думаю главное достоинство — возможность разграничения доступа, например паблик геттер и интернал сеттер. Ну и возможность выполнения дополнительного кода при обращении как с полями.
Как по мне, то разграничение доступа — это главное достоинсво отдельных методов, а не свойств.
Пример:
private int m_field;
protected abstract int GetField();
internal void SetField(int value)
{
m_field = value;
}
Я отнюдь не противник свойств, но это лишь удобство, а не необходимость.
Здравствуйте, Mab, Вы писали:
Mab>Здравствуйте, _d_m_, Вы писали:
Mab>Одно из преимуществ propreties -- это связность getter-а и setter-а на уровне метаданных с введением новой, вполне естественной сущности. Возможность писать ABC, а не get_ABC(), set_ABC() -- это не более, чем приятный синтаксический сахар.
___>>А семантика полей и проперти совпадают. Только в случае проперти можно реально огрести. Типа исключений, неочевидных изменений состояния объекта и прочего. К Рихтеру. Mab>Все это примеры неудачного дизайна и использования properties не по назначению.
Ага, я решил в своем проекте использовать сборку Васи Пупкина. Где гарантия, что он их использовал по назначению? Уж если даже в самой FCL они не всегда по назначению. Это как с управлением памятью в C/C++ — надо просто ее всегда ее освобождать. Но... не всегда получалось — и память текла. И тогда подумали и сделали .Net и в нем GC. Чуствуешь взаимосвязь?
Имхо, все перечисленные пункты — не проблема. Совсем не проблема. Так говорит мне опыт.
Единственное что реально мешает это — Причина в том, что свойства выглядят как поля, на самом деле являясь методами.
Но этого мы избегаем, называя переменные с маленькой буквы, а свойства с заглавной.
Имхо, Рихтер не программировал сам на C# столько же много, как мы с вами.
Здравствуйте, Pro100Oleh, Вы писали:
PO>Здравствуйте, AK85, Вы писали:
AK>>Я думаю главное достоинство — возможность разграничения доступа, например паблик геттер и интернал сеттер. Ну и возможность выполнения дополнительного кода при обращении как с полями.
PO>Как по мне, то разграничение доступа — это главное достоинсво отдельных методов, а не свойств. PO>Пример: PO>
Здравствуйте, Andrbig, Вы писали:
A>Если твой Рихтер сказал это тебе нежно на ушко — про такого не знаю. А если это тот, который автор книг — слышал и хочется увидеть цитаты.
Акстись. Это форум по программированию. Могу тебе кое что сказать на ушко — только получится совсем не нежно.
Здравствуйте, _ks_, Вы писали:
__>Имхо, все перечисленные пункты — не проблема. Совсем не проблема. Так говорит мне опыт. __>Единственное что реально мешает это — Причина в том, что свойства выглядят как поля, на самом деле являясь методами. __>Но этого мы избегаем, называя переменные с маленькой буквы, а свойства с заглавной.
Ну отлично. А Вася Пупкин так не делает. А мы вот используем его сборки в своих проектах.
__>Имхо, Рихтер не программировал сам на C# столько же много, как мы с вами.
Ммм... А PowerCollections не его фирма писала? Я Рихтера помню еще с... Win NT 3.51. Рихтер это мужик с большой буквы — я о его книгах по программированию. И опыт у него огромный — не как "у нас с вами".
Я Рихтера помню еще с... Win NT 3.51. Рихтер это мужик с большой буквы — я о его книгах по программированию. И опыт у него огромный — не как "у нас с вами".
__>>Имхо, все перечисленные пункты — не проблема. Совсем не проблема. Так говорит мне опыт. __>>Единственное что реально мешает это — Причина в том, что свойства выглядят как поля, на самом деле являясь методами. __>>Но этого мы избегаем, называя переменные с маленькой буквы, а свойства с заглавной.
___>Ну отлично. А Вася Пупкин так не делает. А мы вот используем его сборки в своих проектах.
Да, здесь начинаются "проблемы".
Интелисенс всегда покажет свойство это или переменная.
__>>Имхо, Рихтер не программировал сам на C# столько же много, как мы с вами. ___>Ммм... А PowerCollections не его фирма писала? Я Рихтера помню еще с... Win NT 3.51. Рихтер это мужик с большой буквы — я о его книгах по программированию. И опыт у него огромный — не как "у нас с вами".
Здравствуйте, Farsight, Вы писали:
F>Здравствуйте, _d_m_, Вы писали:
___>>А семантика полей и проперти совпадают. Только в случае проперти можно реально огрести. Типа исключений, неочевидных изменений состояния объекта и прочего. К Рихтеру.
F>Ну это сказки. Посмотри в MSIL. Там компилятором генерируются те же геттеры и сеттеры. Это не более чем повышение комфорта при программировании.
В смысле — сказки? Что я не могу огрести исключение при обращении к свойству?
class MyClass
{
private int i_prop;
public int Prop
{
set
{
if( value > 100 )
throw new Exception("А вот хрен");
this.i_prop = value;
}
}
}
Здравствуйте, _d_m_, Вы писали:
Mab>>Все это примеры неудачного дизайна и использования properties не по назначению.
___>Ага, я решил в своем проекте использовать сборку Васи Пупкина. Где гарантия, что он их использовал по назначению?
А где гарантия, что Вася, например, не написал метод get_Something(), который меняет состояние объекта?
What a piece of work is a man! how noble in reason! how infinite in faculty! in form and moving how express and admirable! in action how like an angel! in apprehension how like a god! the beauty of the world! the paragon of animals!
Здравствуйте, _d_m_, Вы писали:
___>Здравствуйте, _ks_, Вы писали:
__>>Имхо, все перечисленные пункты — не проблема. Совсем не проблема. Так говорит мне опыт. __>>Единственное что реально мешает это — Причина в том, что свойства выглядят как поля, на самом деле являясь методами. __>>Но этого мы избегаем, называя переменные с маленькой буквы, а свойства с заглавной.
___>Ну отлично. А Вася Пупкин так не делает. А мы вот используем его сборки в своих проектах.
А нефиг использовать сбоки Васьки. Раз он с архитектурой не дружит, то всяко код его кривой.
Что до свойств: лично я привык, чтобы все поступающие из вне данные обрабатывались на предмет валидности. Так что public только свойства. Все private-поля пишуться с маленькой буквы. protected-поля не использую (все изменения через свойства базового класса). Все работает
Здравствуйте, _d_m_, Вы писали:
___>Здравствуйте, _ks_, Вы писали:
__>>В C# (начиная с 2.0) можно иметь различный доступ к set и get методам одного свойства.
___>Это мало что меняет.
Не понял... Вы это о чем?
Человек сказал: "Жаль нету разграничения по дуступу". Я ответил "Есть с версии 2.0". А Вы говорите "Это мало что меняет".
Вы хотели сказать, что даже если есть разграничение по доступу, то его нет?
Здравствуйте, _ks_, Вы писали:
___>>Это мало что меняет.
__>Не понял... Вы это о чем? __>Человек сказал: "Жаль нету разграничения по дуступу". Я ответил "Есть с версии 2.0". А Вы говорите "Это мало что меняет".
__>Вы хотели сказать, что даже если есть разграничение по доступу, то его нет?
Реализуй мой пример с помощью свойств на C#, и тогда станет ясно, почему "разграничения по дуступу" "мало что меняет".
Здравствуйте, _d_m_, Вы писали:
__>>Единственное что реально мешает это — Причина в том, что свойства выглядят как поля, на самом деле являясь методами. __>>Но этого мы избегаем, называя переменные с маленькой буквы, а свойства с заглавной. ___>Ну отлично. А Вася Пупкин так не делает. А мы вот используем его сборки в своих проектах.
Гм... Ну так надо просто считать, что все, что торчит из класса наружу — это либо метод либо свойство (тоже метод). Собственно, других классов я давно не видел.
What a piece of work is a man! how noble in reason! how infinite in faculty! in form and moving how express and admirable! in action how like an angel! in apprehension how like a god! the beauty of the world! the paragon of animals!
Здравствуйте, _ks_, Вы писали:
__>Имхо, все перечисленные пункты — не проблема. Совсем не проблема. Так говорит мне опыт.
А мне опыт говорит, что это все очень большая проблема. И именно по этому во всех вменяемых стандартах кодирования эти пункты обязательно перечислены в разделе как правильно использовать свойства.
Другое дело, что раз они (свойства) есть, то надо пользоваться ими и запрещать публичные поля.
С преимуществами у них тоже все хорошо, но про недостатки забывать нельзя.
Здравствуйте, _ks_, Вы писали:
__>>>Имхо, Рихтер не программировал сам на C# столько же много, как мы с вами. ___>>Ммм... А PowerCollections не его фирма писала? Я Рихтера помню еще с... Win NT 3.51. Рихтер это мужик с большой буквы — я о его книгах по программированию. И опыт у него огромный — не как "у нас с вами".
__>Я про опыть в C# говорил, а не вообще про опыт.
Ну как сказать. Технологии сменяют друг друга, а опыт в программировании — это как-бы над всем этим. И, кстати, поводу опыта Рихтера в C# — я не сказал, что его у него мало: "А PowerCollections..." это что точно знаю я. Конечно, ты можешь не доверять Рихтеру — это конечно дело твое. Но конкретно с чем ты не согласен? А сказать просто, что Рихтер ламер в С# (при этом не читая его его книг) — это не аргумент и даже как-то смешно.
Здравствуйте, Pro100Oleh, Вы писали:
PO>Здравствуйте, _ks_, Вы писали:
__>>В C# (начиная с 2.0) можно иметь различный доступ к set и get методам одного свойства.
PO>Вы видимо невнимательно посмотрели на мой пример. PO>А про различный доступ я знаю.
Да, я прекрасно вижу, что там стоят abstract и internal.
internal можно заменить private, а если нельзя, то это ооооочень редкий случай.
А abstract вообще никакого отношения к разграничение доступа не имеют.
Ваш пример настолько редок, что не вижу смысла отказыатся от использования свойств только ради него.
__>>Я про опыть в C# говорил, а не вообще про опыт.
___>Ну как сказать. Технологии сменяют друг друга, а опыт в программировании — это как-бы над всем этим.
+1
___>И, кстати, поводу опыта Рихтера в C# — я не сказал, что его у него мало: "А PowerCollections..." это что точно знаю я. Конечно, ты можешь не доверять Рихтеру — это конечно дело твое. Но конкретно с чем ты не согласен?
С тем что перечисленные им проблемы проблемами не являются.
___>А сказать просто, что Рихтер ламер в С# (при этом не читая его его книг) — это не аргумент и даже как-то смешно.
Там (у меня в предложении) стоИт ИМХО. И это ИМХО твёрдое.
___>PS: "Не читал, но осуждаю" (С) Жванецкий
Не читал, но сделанные им выводы меня обескураживают.
Здравствуйте, Hobot Bobot, Вы писали:
HB>Здравствуйте, _d_m_, Вы писали:
Mab>>>Все это примеры неудачного дизайна и использования properties не по назначению.
___>>Ага, я решил в своем проекте использовать сборку Васи Пупкина. Где гарантия, что он их использовал по назначению?
HB>А где гарантия, что Вася, например, не написал метод get_Something(), который меняет состояние объекта?
Гарантии нет, но:
class MyClass
{
private int a;
private int i;
public int I
{
get
{
this.a = 666;
return this.i;
}
}
public int get_I()
{
this.a = 555;
return this.i;
}
}
...
MyClass c = new MyClass();
int d = c.I; // то, что здесь меняется состояние объекта "c" уж очень неочевидноint e = c.get_I();
...
Mab>>>>Все это примеры неудачного дизайна и использования properties не по назначению.
___>>>Ага, я решил в своем проекте использовать сборку Васи Пупкина. Где гарантия, что он их использовал по назначению?
HB>>А где гарантия, что Вася, например, не написал метод get_Something(), который меняет состояние объекта? ___>Гарантии нет, но: ___>
___>...
___> MyClass c = new MyClass();
___> int d = c.I; // то, что здесь меняется состояние объекта "c" уж очень неочевидно
___> int e = c.get_I();
___>...
___>
Это уже индивидуальность восприятия.
Для меня очевидно, потому что имя проперти с большой буквы.
Здравствуйте, c87dlc, Вы писали:
___>>Ну отлично. А Вася Пупкин так не делает. А мы вот используем его сборки в своих проектах.
C>А нефиг использовать сбоки Васьки. Раз он с архитектурой не дружит, то всяко код его кривой.
Не попробуешь — не узнаешь. Это можно сказать только после использования сборки Васьки или сборки фирмы Gigasoft Incorporated. Ведь и там порой работают такие васькИ.
C>Что до свойств: лично я привык, чтобы все поступающие из вне данные обрабатывались на предмет валидности. Так что public только свойства. Все private-поля пишуться с маленькой буквы. protected-поля не использую (все изменения через свойства базового класса). Все работает
Да в принципе все мы молодцы. И код у нас идеальный.
Здравствуйте, Hobot Bobot, Вы писали:
HB>Здравствуйте, _d_m_, Вы писали:
__>>>Единственное что реально мешает это — Причина в том, что свойства выглядят как поля, на самом деле являясь методами. __>>>Но этого мы избегаем, называя переменные с маленькой буквы, а свойства с заглавной. ___>>Ну отлично. А Вася Пупкин так не делает. А мы вот используем его сборки в своих проектах.
HB>Гм... Ну так надо просто считать, что все, что торчит из класса наружу — это либо метод либо свойство (тоже метод). Собственно, других классов я давно не видел.
Спасибо за совет. Обязательно им воспользуюсь. Слушаем да не слышим, смотрим, но не видим?
Здравствуйте, IB, Вы писали:
__>>Имхо, все перечисленные пункты — не проблема. Совсем не проблема. Так говорит мне опыт. IB>А мне опыт говорит, что это все очень большая проблема. И именно по этому во всех вменяемых стандартах кодирования эти пункты обязательно перечислены в разделе как правильно использовать свойства.
А можно пример? А то я когда-то хотел увидеть такие правила, но зубры .Net моё желание не удовлетворили.
Ну, типа, в каких случаях можно писать только сетер, или
* проперти обязаны быть связаны с полями;
или
* сетеры не должны иметь побочных эфектов кроме установки значения поля;
или
... что там пишут то?
Здравствуйте, _ks_, Вы писали:
__>Здравствуйте, _d_m_, Вы писали:
___>>Здравствуйте, _ks_, Вы писали:
__>>>В C# (начиная с 2.0) можно иметь различный доступ к set и get методам одного свойства.
___>>Это мало что меняет.
__>Не понял... Вы это о чем?
О чем сообщение было — не понял, но минус на всякий случай... ммм... зафигачил. Ага, "не читал, но осуждаю"
Здравствуйте, _ks_, Вы писали:
__>Да, я прекрасно вижу, что там стоят abstract и internal. __>internal можно заменить private, а если нельзя, то это ооооочень редкий случай.
Можно так же сказать, что private можно заменить на public и все будет работать. Но ведь нас интересует не только правильная функциональность, но и более полное ограничение членов класса? Вы видимо не обратили внимание на что именно я давал коментарии в этой подветке:
Я думаю главное достоинство — возможность разграничения доступа, например паблик геттер и интернал сеттер.
Я показал, что методы более гибче в разграничении доступа, нежели свойства. (*)
__>А abstract вообще никакого отношения к разграничение доступа не имеют.
Согласен, просто я показал дополнительные преимущества над свойствами.
__>Ваш пример настолько редок, что не вижу смысла отказыатся от использования свойств только ради него.
Я не пытался убедить отказаться от свойств, я лишь хотел сказать следующее: (см *)
Здравствуйте, _d_m_, Вы писали:
___>Здравствуйте, _ks_, Вы писали:
__>>Здравствуйте, _d_m_, Вы писали:
___>>>Здравствуйте, _ks_, Вы писали:
__>>>>В C# (начиная с 2.0) можно иметь различный доступ к set и get методам одного свойства.
___>>>Это мало что меняет.
__>>Не понял... Вы это о чем?
___>О чем сообщение было — не понял, но минус на всякий случай... ммм... зафигачил. Ага, "не читал, но осуждаю"
Аааа... минус. Я его поставил сначала, потому что мне показались что Ваши слова противоречивы (и до сих пор кажутся). А потом еще раз подумал, а потом еще раз, а потом еще раз, а потом перестал работать и написал ответ.
PO>Я показал, что методы более гибче в разграничении доступа, нежели свойства. (*)
Понятно. Спасибо.
Согласен, что методы гибче. Но там где гибкость не нужна...
__>>А abstract вообще никакого отношения к разграничение доступа не имеют. PO>Согласен, просто я показал дополнительные преимущества над свойствами.
__>>Ваш пример настолько редок, что не вижу смысла отказыатся от использования свойств только ради него. PO>Я не пытался убедить отказаться от свойств, я лишь хотел сказать следующее: (см *)
Просто Ваш пост находится в самой гуще треда "проперти использовать низя!". Вот мне и показалось, что Вы поддерживаете эту точку зрения.
Здравствуйте, Andrei N.Sobchuck, Вы писали:
IB>>А мне опыт говорит, что это все очень большая проблема. И именно по этому во всех вменяемых стандартах кодирования эти пункты обязательно перечислены в разделе как правильно использовать свойства.
ANS>А можно пример? А то я когда-то хотел увидеть такие правила, но зубры .Net моё желание не удовлетворили. ANS>Ну, типа, в каких случаях можно писать только сетер, или ANS>* проперти обязаны быть связаны с полями; ANS>или ANS>* сетеры не должны иметь побочных эфектов кроме установки значения поля; ANS>или ANS>... что там пишут то?
Я думаю, что IB имел ввиду, что в документации должно быть описано, что собой представляет свойство.
Пример:
public class Provider
{
private PropertyCollection m_properties;
public PropertyCollection Properties
{
get
{
return m_properties;
}
}
/// <summary>
/// DBService has own db connection
/// </summary>public DBService Service
{
get
{
return new DBService(m_properties.ConnectionString);
}
}
}
class Program
{
static void Main(string[] args)
{
Provider provider = new Provider();
//correct
provider.Properties.Name = "provider";
provider.Properties.ConnectionString = "bla bla";
//correct, but not optimal (two connection)
provider.Service.GetTable1Content();
provider.Service.GetTable2Content();
//good practice (one connection)
DBService service = provider.Service;
service.GetTable1Content();
service.GetTable2Content();
}
}
Когда программист использует свойство, он должен хорошо представлять его действия.
P.S. Прошу не писать, что в данном случае нужно было спользовать метод, это просто пример для демонстрации идеи.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, _d_m_, Вы писали:
L>>>Имхо, чтобы избежать перечисленного нет необходимости отказываться от свойств. Достаточно всего лишь запретить не-приватные поля.
___>>Но это совсем ничего не изменит.
L>Изменит все. Ни один пункт из аргументации работать не будет.
Вот незадача! А мы с Рихтером как-то и не догадались. Надо ему будет как-нибудь "нашептать на ушко".
Здравствуйте, _ks_, Вы писали:
__>Рвз уж мы переехали в Философию программирования, то спрошу начитанную общественность вот что.
__>Какая практическая польза от здесь сахара?
Здравствуйте, IB, Вы писали:
IB>4. Не используйте публичные поля, вместо них следует использовать свойства.
Я бы вместо запятой просто поставил точку. Или восклицательный знак Но раз ты так написал, то вопрос, почему так? Чем публичное поле отличается от публичного свойства для пользователя контракта (в смысле для программиста, который пользуется объектом)?
IB>5. Используйте свойства, вместо Get/Set методов.
Тема не раскрыта. Вместо любых или есть какте ограничения?
IB>6. Используйте методы, если выполняемая операция является преобразованием, обладает побочными эффектами, долго выполняется или если важен порядок выполнения операций.
В сетерах часто создаются побочные эфекты. Например создаётся событие "свойство такое-то поменялось". То есть, такого делать нельзя?
IB>7. Свойство не должно менять своего значение от вызова к вызову, если состояние объекта не изменяется.
//correct, but not optimal (two connection)
provider.Service.GetTable1Content();
provider.Service.GetTable2Content();
выделено мной. То есть так нельзя?
IB> Если результат при новом вызове может быть другим при том же состоянии объекта, используйте метод.
IB>8. Не используйте свойства «только для записи». Потребность в таком свойстве может быть признаком плохого проектирования. IB>.... IB>[/q]
А сразу в несколько полей из одного свойства можно писать?
Здравствуйте, Andrei N.Sobchuck, Вы писали:
ANS>Но раз ты так написал, то вопрос, почему так?
Я не написал, я процитировал.
ANS> Чем публичное поле отличается от публичного свойства для пользователя контракта (в смысле для программиста, который пользуется объектом)?
Хотя бы метаданными.
ANS> Вместо любых или есть какте ограничения?
Никиких, кроме процитированных.
ANS>В сетерах часто создаются побочные эфекты.
А ты не создавай.
ANS> Например создаётся событие "свойство такое-то поменялось".
Событие — это не побочный эффект.
ANS>Хе-хе. А вот пишут
Здравствуйте, iZEN, Вы писали:
ZEN>А если нужно перегрузить Get()/Set() в потомках?
Тогда так:
int networkID;
publicvirtualint NetworkID
{
get { return this.networkId; }
set { this.networkId = value; }
}
What a piece of work is a man! how noble in reason! how infinite in faculty! in form and moving how express and admirable! in action how like an angel! in apprehension how like a god! the beauty of the world! the paragon of animals!
Здравствуйте, Mab, Вы писали:
Mab>Здравствуйте, _d_m_, Вы писали:
___>>Ага, я решил в своем проекте использовать сборку Васи Пупкина. Где гарантия, что он их использовал по назначению? Уж если даже в самой FCL они не всегда по назначению. Это как с управлением памятью в C/C++ — надо просто ее всегда ее освобождать. Но... не всегда получалось — и память текла. И тогда подумали и сделали .Net и в нем GC. Чуствуешь взаимосвязь?
Mab>Думаю, что Васю Пупкина и GC не остановит.
Нет ну бывают, конечно, кадры. Но они все-таки редки. Вася Пупкин в моем примере имено средний, а не уж совсем ламер. Ну не читал он не Рихтера, не умных форумов. Он просто работает, звезд с небес не хватает, не интересует его ничего, кроме того, что касается непосредсвенно работы. В форумах таких много — им даже лень открыть документацию, поискать гуглем. Васи Пупкины повсюду.
Mab>ИМХО возможность для низкоквалифицированных кадров устроить неприятность не должна быть ключевым аргументом за или против. Зачем нам равняться на команды посредственностей?
А как? Ориентироваться на команду гениев?
Один из законов Мерфи: "Если что-то может быть сделано неправильно — оно будет сделано неправильно". И как показывает, во всяком случае, мой опыт — так бывает нередко. Уж сколько я имел дела c софтом третьих фирм или с драйверами вендоров... Команды Васей Пукиных все-таки не редкость.
Mab>Уровень дуракоустойчивости должен быть разумным.
Согласен. Но речь здесь идет о синтаксическом сахаре — свойствах.
___>... ___>- метод свойства может привести к исключению, а при доступе к полям исключений не бывает;
В c# и так много мест где могут кидаться исключения. Подумаешь исключением больше, исключением меньше.
___>... ___>- метод свойства может выполнятся довольно долго, а доступ к полям выполняется моментально. Часто свойства используют для синхронизации потоков, но это может привести к приостановке потока на неопределенное время — поэтому свойства не следует использовать для этих целей — в такой ситуации лучше задействовать метод. Кроме, того если предусмотрен удаленный доступ к классу (например, если он наследует System.MarshalByRefObject), вызов метода свойства выполнится очень медленно, поэтому предпочтение следует отдать методу. Я считаю, что в классах, производных от MarshalByRefObject, никогда не следует использовать свойства;
Лично я без профайлера все равно не смогу сказать сколько времени будет выполняться код. А от того вместо o.Foo будем писать o.GetFoo код быстрее не станет.
___>- при вызове несколько ряд подряд метод свойства может возвращать разные значения, а поле возвращает одно и тоже значение. В классе System.DateTime есть неизменяемое свойство Now ...
Ну есть косячок. Но неужели у кого-то с этим свойством проблемы?
___>- метод свойства может создавать наблюдаемые стороние эффекты, а при доступе к полю это невозможно...
Было бы желание. Где гарантия что Вася Пупкин не запустил второй поток который проверяет не изменилось ли поле?
___>- методу свойства может требоваться дополнительная память или ссылка на объект, не являющаяся частью состояния объекта, поэтому изменение возвращаемого объекта никак не сказывается на исходном объекте; при запросе поля всегда возвращается ссылка на объект, который гарантировано относиться к состоянию исходного объекта. Свойство, возвращающее копию, — источник замешательства для разработчиков, причем это поведение часто забывают упомянуть в документации.
Классы Васи Пупкина сами по себе источник замешательства для разработчиков. Неважно используют ли они свойства или нет.
___>PS: Ну так чей код "не приведи господь" лучше поддерживать?
Не приведи господь поддерживать код Васи Пупкина.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, iZEN, Вы писали:
_FR>
IB>>>Свойство не должно менять своего значение от вызова к вызову, если состояние объекта не изменяется.
IB>>>выделено мной. iZEN>>Это прерогатива поля. _FR>Что именно? Невозможность изменить своё значение? Как бы ни так
В случае со свойством сложно-составной геттер может иметь собственную семантику, "продолжительность" во времени и много "внешних" зацеплений. Поэтому говорить о полной атомарности свойства нельзя. Я так думаю.
Здравствуйте, Константин Б., Вы писали:
КБ>Здравствуйте, _d_m_, Вы писали:
___>>... ___>>- метод свойства может привести к исключению, а при доступе к полям исключений не бывает; КБ>В c# и так много мест где могут кидаться исключения. Подумаешь исключением больше, исключением меньше.
Вот к чему приводит отсутствие checked-exceptions -- к наплевательскому отношению к коду, выполняющемуся к тому времени уже у клиента.
Здравствуйте, iZEN, Вы писали:
ZEN>В случае со свойством сложно-составной геттер может иметь собственную семантику, "продолжительность" во времени и много "внешних" зацеплений. Поэтому говорить о полной атомарности свойства нельзя. Я так думаю.
А зачем нужна "полной атомарность"? Вызывающая сторона не должна об этом беспокоиться, это проблема того, кто реализует свойство: сделать его так, как будет написано в документации или как требуется по соглашениям (например, при переопределении).
В тех случаях () когда вызывающему коду гарантированно требуется "полная атомарность", тому (вызывающему) следует сохранить значение свойства в переменной и пользоваться ею. Но ведь таких "случаев" должно быть очень мало (неужели у вас много? а почему?) и проблем это не составляет.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, iZEN, Вы писали:
ZEN>В случае со свойством сложно-составной геттер может иметь собственную семантику,
Может, но не должен. О чем собственно и речь.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, iZEN, Вы писали:
iZEN>>Вот к чему приводит отсутствие checked-exceptions -- к наплевательскому отношению к коду, выполняющемуся к тому времени уже у клиента. IB>А присутствие к такому геморрою, что лучше бы их не было.
Этот "геморрой" проверяется компилятором на этапе компиляции (или сразу в редакторе кода) , в отличие от... непроверяемого геморроя.
Здравствуйте, iZEN, Вы писали:
ZEN>Этот "геморрой" проверяется компилятором на этапе компиляции (или сразу в редакторе кода) , в отличие от... непроверяемого геморроя.
Я немного не в курсе… А проверятся ли он в рантайме? То есть, пускай есть метод A, в котором сказано, что он бросает только исключение E, и этот метод находится в отдельной библиотеки D. Я использую её в своём приложении и вызываю метод A. Далее. у пользователя моей программы оказалась более новая версия библиотеки D: D1, но метод A в этой библиотеке уже выбрасывает исключение E1. Что произойдёт при попытке вызова моей программой метода A?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, iZEN, Вы писали:
ZEN>>Этот "геморрой" проверяется компилятором на этапе компиляции (или сразу в редакторе кода) , в отличие от... непроверяемого геморроя.
_FR>Я немного не в курсе… А проверятся ли он в рантайме? То есть, пускай есть метод A, в котором сказано, что он бросает только исключение E, и этот метод находится в отдельной библиотеки D. Я использую её в своём приложении и вызываю метод A. Далее. у пользователя моей программы оказалась более новая версия библиотеки D: D1, но метод A в этой библиотеке уже выбрасывает исключение E1. Что произойдёт при попытке вызова моей программой метода A?
В Java в потомке (более новая версия библиотеки) никогда нельзя бросить контролируемое исключение в переопределённом методе, не объявленное (или не принадлежащее ветки наследования объявленного контролируемого исключения) в методе родительского класса -- компилятор завернёт такой код, то есть чужая "более новая версия библиотеки" невозможна, либо несовместима уже на стадии загрузки и верификации такого кода.
Компилятор Java навязывает применение "того же или меньшего набора контролируемых исключений" в новом коде для потомков начального класса.
Здравствуйте, iZEN, Вы писали:
ZEN>Компилятор Java навязывает применение "того же или меньшего набора контролируемых исключений" в новом коде для потомков начального класса.
Я же говорил совсем не об этом: я спрашивал, как себя ведёт рантайм
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, iZEN, Вы писали:
iZEN>>Этот "геморрой" проверяется компилятором на этапе компиляции (или сразу в редакторе кода) IB>Угу, то-то большинство явистов, оптом предпочитают декларировать одно большое исключение на все случаи жизни, чтобы компилятор лишний раз не тревожил. Похоже классический пример, когда лекарство хуже болезни.
Прошу прощения, что увёл тему не в то русло.
Но это ваше "большинство явистов" либо не умеют программировать логику обработки контролируемых исключений, либо не знакомы с EJB (где повсеместно используются неконтролируемые исключения, откуда бы они черпали идеи для реализации), что в любом случае говорит об их низкой квалификации.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, iZEN, Вы писали:
ZEN>>Компилятор Java навязывает применение "того же или меньшего набора контролируемых исключений" в новом коде для потомков начального класса.
_FR>я спрашивал, как себя ведёт рантайм
Ошибка на стадии верификации кода и невозможности продолжения исполнения приложения в момент загрузки класса из новой библиотеки.
Здравствуйте, iZEN, Вы писали:
ZEN>Ошибка на стадии верификации кода и невозможности продолжения исполнения приложения в момент загрузки класса из новой библиотеки.
А теперь грабли: список исключений, выбрасываемых методом не является частью сигнатуры метода и, =>, вот какая получается штука: написал я свой приложение с использованием библиотеки D и отдал пользователям. И, как только у тех оказалась новая версия библиотеки D, моя программа перестала работать, ибо не прошла "верификация кода"
Тоже самое может быть и сейчас, когда в новой версии может вообще не оказаться метода, который был в предыдущей и который вызывает моя программа. Но в таком случае _хорошие_ дяденьки-разработчики библиотеки D могут оставить мне мой метод и либо ничего в нём не делать, либо делать что-то умолчательное, либо вызывать новый метод. Суть в том, что в одной сборке могут одновременно существовать и старые, и новые сущности. А если сущность (метод в нашем случае) осталась прежней, а изменились исключения то это уже непоправимо для меня или нет? Как можно поступить в такой ситуации?
Help will always be given at Hogwarts to those who ask for it.
IB wrote: > ZEN>В случае со свойством сложно-составной геттер *может* иметь > собственную семантику, > Может, но не должен. О чем собственно и речь.
А как быть с вещами типа lazy-loading/lazy-creation?
Здравствуйте, _d_m_, Вы писали:
HB>>Здравствуйте, _d_m_, Вы писали:
__>>>>Единственное что реально мешает это — Причина в том, что свойства выглядят как поля, на самом деле являясь методами.
HB>>Гм... Ну так надо просто считать, что все, что торчит из класса наружу — это либо метод либо свойство (тоже метод). Собственно, других классов я давно не видел.
___>Спасибо за совет. Обязательно им воспользуюсь. Слушаем да не слышим, смотрим, но не видим?
Здравствуйте, Константин Б., Вы писали:
___>>- при вызове несколько ряд подряд метод свойства может возвращать разные значения, а поле возвращает одно и тоже значение. В классе System.DateTime есть неизменяемое свойство Now ... КБ>Ну есть косячок. Но неужели у кого-то с этим свойством проблемы?
Хм, а какие проблемы? Оно же статическое к тому-же... И объект вроде один — время — и состояние постоянно меняется.
Здравствуйте, squiz, Вы писали:
___>>Спасибо за совет. Обязательно им воспользуюсь. Слушаем да не слышим, смотрим, но не видим?
S>Ну вы-то похоже точно!
Здравствуйте, Cyberax, Вы писали:
C>А как быть с вещами типа lazy-loading/lazy-creation?
Во-первых, а что тут не так с семантикой геттера?
А во-вторых — Следовать SRP.
Умение себя загружать или создавать — это не свойство объекта (объект другоми вещами заниматься должен), это свойство "загружателя" и "создавателя". Следовательно, вся эта ленивость содержится в соответствующих методах "загружателей" и "создавателей".
Здравствуйте, iZEN, Вы писали:
ZEN>Но это ваше "большинство явистов" либо не умеют программировать логику обработки контролируемых исключений, либо не знакомы с EJB (где повсеместно используются неконтролируемые исключения, откуда бы они черпали идеи для реализации), что в любом случае говорит об их низкой квалификации.
=> большинство явистов обладают низкой квалификацией..
Здравствуйте, Sinclair, Вы писали:
S>Еще он предлагал чтобы реализация object.Equals всегда возвращала true. Так, дескать, не будет разницы при перегрузке Equals, от какого класса мы наследуемся. Реальный бред — в дизни перегрузка Equals встречается очень редко, и она требует высокой квалификации. Иначе можно наделать чудных граблей. А вот рекомендация Рихтера махом привела бы к тому, что у всех экземпляров любого ссылочного типа был бы одинаковый хэш-код. И Equals приходилось бы перегружать на каждый чих. В общем, тяжелая наркомания налицо.
Хм, а вообще нужно ли перегружать Equals и GetHashCode у классов с reference-type семантикой? ИМХО, они (а так же интерфейс IComparable) как раз и нужны для эмуляции сущностей с value-type семантикой. Или бывают ещё случаи?
Кстати, а как работает object.GetHashCode()? Я так понимаю, он жёстко привязывается к объекту. Т.е. должно быть какое-то спец. поле у каждого объекта. Но, видимо, это не так...
Здравствуйте, AndrewVK, Вы писали:
_FR>>А теперь грабли: список исключений, выбрасываемых методом не является частью сигнатуры метода
AVK>В джаве является.
Вау, то есть в классе могут быть два метода с одинаковым списком входных параметров и различающимися только секцией throws?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Sinclair, Вы писали:
K>>Хм, а вообще нужно ли перегружать Equals и GetHashCode у классов с reference-type семантикой? S>У них — нет. S>Но в жизни классы с value-type семантикой встречаются достаточно часто. Я, кстати, до сих пор не знаю, как ими правильно пользоваться.
Как и обычными value в ФЯ. Просто делаем аналог алгебраического типа с одним конструктором. Я подобные классы оформляю согласно следующему паттерну:
public class MyClass
{
public static readonly MyClass SpecialCase1 = new MyClass(...);
public readonly ValueType Param1;
private readonly ImmutableInterfaceImplementor param2;
public readonly ReferenceType Param3;
// Может быть и private, тогда предполагается создание объекта через
// статический метод-конструкторpublic MyClass(ValueType param1, IReadOnlyInterface param2, ReferenceType param3)
{
this.Param1 = param1;
// Обязательно делаем локальную иммутабельную копию!
// ImmutableInterfaceImplementor тоже должен иметь value-type семантику.this.param2 = new ImmutableInterfaceImplementor(param2);
this.Param3 = param3;
}
public static MyClass SpecialConstructor(...)
{
// ...
}
public IReadOnlyInterface Param2
{
get
{
return param2;
}
}
public static bool operator ==(MyClass a, MyClass b)
{
if (object.ReferenceEquals(a, b))
return true;
return
a.Param1 == b.Param1 &&
a.param2 == b.param2 &&
a.Param3 == b.Param3;
}
public static bool operator !=(MyClass a, MyClass b)
{
return !(a == b);
}
public override int GetHashCode()
{
// Возможна ленивая реализация для больших объектов. При этом заводятся мутабельны поля
// hash = 0 и needHash = true.
//return
(a.Param1.GetHashCode() << 2) ^
(a.param2.GetHashCode() << 1) ^
a.Param3.GetHashCode();
}
public override bool Equals(object obj)
{
if (!(obj is MyClass))
return false;
return this == ((MyClass)obj);
}
}
Немного задалбывает в таких случаях пороться со стандартными дотнетовскими коллекциями. Я даже всё время обещаю себе написать небольшую библиотеку для эмуляции функционального стиля, но всё руки не доходят.
Для эмуляции алгебраических типов с несколькими конструкторами юзаю более сложный паттерн, с вложенными sealed-классами, одновременно наследующими абтрактный родительский класс.
Надо сказать, что в последнее время мне нравится совмещать ФП и ООП стили. Потому объекты с value-type семантикой у меня в коде попадаются весьма часто. Например, в отличие от известных мне GUI-библиотек, в своей я сделал вещи вроде Brush, Pen, Font value-типами, причём Brush — аналог алебраического типа с несколькими конструкторами (Flat, LinearGradient, RadialGradient, Transparent, Inherit).
S>Во мне крепнет убеждение, что value-type семантика однозначно требует immutability, иначе начинаются чудные спецэффекты. Посудите сами: Equals придуман так, что если два объекта в какой-то момент времени эквивалентны, то так будет и навсегда в будущем. На этом, в частности, построены все коллекции, которые вообще используют Equals. Из этого непосредственно следует, что если Equals строится на состоянии объекта, то это состояние нельзя изменять. В свете этого, мне вообше непонятно, зачем в дотнете разрешили сочетать перегрузку Equals/GetHashCode для изменяемых объектов.
Вот именно. Но вот в чём беда: любой класс может быть использован как ключ в словаре. Это источник потенциальных ошибок. Правда, это не значит, что мне, допустим, не надо иметь множество объектов с reference-type семантикой, потому интерфейс тут не подошёл бы. Потому при документировании нужно явно указывать, какую семантику имеет объект. Хотя это порождает вопрос: а как быть с индусокодерами, которые над подобными вещами не задумываются.
S>Хэш-код — это всего лишь приятное дополнение к методу Equals, более грубое разбиение на классы эквивалентности.
Ага. Только Equals должен разбивать на классы по отношению равенства. ИМХО, всякие отношения (эквивалентности, порядка и т.п.), если они нужны в каких-то методах, должны явно передаваться этим методам, а не браться из классов. Т.е. Equals, GetHashCode и IComparable должны использоваться исключительно для того, чтобы эмулировать ФП, и не для чего-либо ещё.
Здравствуйте, Mab, Вы писали:
Mab>Есть такое поле, sync block index называется. Оно же заодно связано с объектом синхронизации, который потенциально может быть заведен для любого экземпляра.
А значение поля уникально для каждого объекта? Меня это интересует в свете того, что в Nemerle Set['a] и Map['a] имеют ограничение IComparable['a], а мне хотелось бы его снять...
Здравствуйте, konsoletyper, Вы писали:
K>А значение поля уникально для каждого объекта?
Оно постоянно все время жизни объекта, но не уникально, так что возможны коллизии. Линейного порядка на них не построишь, увы.
Здравствуйте, _FRED_, Вы писали:
AVK>>В джаве является.
_FR>Вау, то есть в классе могут быть два метода с одинаковым списком входных параметров и различающимися только секцией throws?
А кто сказал что перегрузка обязана быть возможной по любой части сигнатуры?
Здравствуйте, AndrewVK, Вы писали:
AVK>>>В джаве является. _FR>>Вау, то есть в классе могут быть два метода с одинаковым списком входных параметров и различающимися только секцией throws? AVK>А кто сказал что перегрузка обязана быть возможной по любой части сигнатуры?
Ага, ты понимаешь под сигнатурой контракт метода? Мне казалось, что сигнатура это вот.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, AndrewVK, Вы писали:
_FR>>Ага, ты понимаешь под сигнатурой контракт метода? Мне казалось, что сигнатура это вот.
AVK>То есть, по твоему, в C# можно перегружать по типу возвращаемого значения?
The signature of a method specifically does not include the return type, parameter names, or
type parameter names, nor does it include the params modifier that can be specified for the right-most
parameter.
Тем не менее, различие в сигнатурах не всегда влечет возможность перегрузки. Например:
Although out and ref parameter modifiers are considered part of a signature, members declared in a single
type cannot differ in signature solely by ref and out.
Здравствуйте, Sinclair, Вы писали:
S>Еще он предлагал чтобы реализация object.Equals всегда возвращала true. Так, дескать, не будет разницы при перегрузке Equals, от какого класса мы наследуемся. Реальный бред — в дизни перегрузка Equals встречается очень редко, и она требует высокой квалификации. Иначе можно наделать чудных граблей. А вот рекомендация Рихтера махом привела бы к тому, что у всех экземпляров любого ссылочного типа был бы одинаковый хэш-код. И Equals приходилось бы перегружать на каждый чих. В общем, тяжелая наркомания налицо.
Я специально перечитал не моргая параграф "Тождество и равенство", где подробно обсуждается Object.Equals() и Object.GetHashCode() и не нашел даже намека на: "чтобы реализация object.Equals всегда возвращала true". Где это написано, если не секрет? Или голоса в голове подсказали? Или, как мне тут уже объяснили, это какой-то другой Рихтер с которым я перешептываюсь нежно на ушко.
Здравствуйте, _d_m_, Вы писали: ___>Я специально перечитал не моргая параграф "Тождество и равенство", где подробно обсуждается Object.Equals() и Object.GetHashCode() и не нашел даже намека на: "чтобы реализация object.Equals всегда возвращала true". Где это написано, если не секрет? Или голоса в голове подсказали? Или, как мне тут уже объяснили, это какой-то другой Рихтер с которым я перешептываюсь нежно на ушко.
К моему прискорбию, это в нем вычитал не я — мне показывали фрагмент из ебука во время спора на эту тему. Вот поклонник Рихтера выйдет из отпуска — я поточнее посмотрю, откуда дровишки.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>К моему прискорбию, это в нем вычитал не я — мне показывали фрагмент из ебука во время спора на эту тему. Вот поклонник Рихтера выйдет из отпуска — я поточнее посмотрю, откуда дровишки.
Идея Рихтера была в том, что метод Equals по умолчанию для ссылочных типов должен возвращать true, если совпадают типы сравниваемых объектов. См. CLR via C#, Издательство Питер, 2007 г., стр. 138-139.
Здравствуйте, nikov, Вы писали: N>Идея Рихтера была в том, что метод Equals по умолчанию для ссылочных типов должен возвращать true, если совпадают типы сравниваемых объектов. См. CLR via C#, Издательство Питер, 2007 г., стр. 138-139.
Да-да, я и говорю — полный бред. То есть наследуемся мы от object, создавая класс, скажем, Test. Дотнет считает (по умолчанию) любые два экземпляра этого класса различными, т.е. Equals вернет для них false.
Рихтер предлагает по умолчанию считать любые два экземпляра этого класса эквивалентными. Надо полагать, от большого ума.
Программисты не очень часто напрямую вызывают Equals. Не все из них ожидают засады при использовании, к примеру, Dictionary<Test, int>. Или от List<Test>.IndexOf(). Ой не все.
Кстати, напомни мне, какую реализацию GetHashCode предлагает Рихтер вместе с таким замечательным Equals?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Кстати, напомни мне, какую реализацию GetHashCode предлагает Рихтер вместе с таким замечательным Equals?
Он считает, что метод GetHashCode не должен быть членом System.Object, а должен быть членом специального интерфейса и реализовываться только там, где нужно.
Здравствуйте, nikov, Вы писали:
S>>Кстати, напомни мне, какую реализацию GetHashCode предлагает Рихтер вместе с таким замечательным Equals?
N>Он считает, что метод GetHashCode не должен быть членом System.Object, а должен быть членом специального интерфейса и реализовываться только там, где нужно.
Здравствуйте, nikov, Вы писали: N>см. там же, стр. 92, таблица внизу.
Отлично. В принципе, это наверное бы даже сработало, но тогда бы коллекции пришлось бы ограничить констреинтом на реализацию этого интерфейса.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
N>>см. там же, стр. 92, таблица внизу. S>Отлично. В принципе, это наверное бы даже сработало, но тогда бы коллекции пришлось бы ограничить констреинтом на реализацию этого интерфейса.
Не обязательно: его можно передовать отдельно, как IEqualityComparer<T> сейчас в Dictionary<,>.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, nikov, Вы писали:
S>>Кстати, напомни мне, какую реализацию GetHashCode предлагает Рихтер вместе с таким замечательным Equals?
N>Он считает, что метод GetHashCode не должен быть членом System.Object, а должен быть членом специального интерфейса и реализовываться только там, где нужно.
А зачем Equals(object) в System.Object? Имхо, IEqualityComparer<> (и\или не-generic IEqualityComparer [которого сейчас нет]) решили бы дело
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, konsoletyper, Вы писали:
K>Здравствуйте, _d_m_, Вы писали:
___>>Еще один "не читал, но осуждаю".
K>[skip]
K>Ну вот, прочитали. Теперь осуждеаем квалифицированно. Рихтер в своих рассуждениях забывает тот факт, что вообще не для всех объектов (причём далеко не для всех) есть смысл переопределять Equals. В ООП объекты обладают identity, и сравнивать их, соотвественно, имеет смысл только по этому identity. Equals был введён для грубой эмуляции ФП.
Он не утверждает, что надо для всех объектов надо переопределять Equals. Он рассуждает о том, как надо было бы Microsoft это сделать для Object и если уж надо переопределять Equals, то как.
Здравствуйте, _d_m_, Вы писали: ___>Еще один "не читал, но осуждаю".
О, спасибо. Я как раз это и искал.
Все, кроме вот этого комментария можно опустить: ___> // Т.к. в System.Object не определены поля, следует считать, что поля равны ___> return true;
Как я и говорил, это приведет к тому, что если не переопределить Equals в наследнике Object, то унаследованная реализация вернет true для любой пары объектов. Предлагать это — вопиющее ламерство; я не понимаю, как человек с опытом программирования решается предлагать такие идиотизмы.
Кстати, ты не мог бы озвучить весь список предложенных Рихтером "улучшений" для CLR?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
___>> // Т.к. в System.Object не определены поля, следует считать, что поля равны ___>> return true; S>Как я и говорил, это приведет к тому, что если не переопределить Equals в наследнике Object, то унаследованная реализация вернет true для любой пары объектов.
S>>Как я и говорил, это приведет к тому, что если не переопределить Equals в наследнике Object, то унаследованная реализация вернет true для любой пары объектов.
_FR>Мне показалось _FR>
_d_m_ wrote: > Вот как нужно это делать: > 1. Если аргумент obj равен null, вернуть false.
В этом случае лучше кинуть NullReferenceException — чтобы сохранить
коммутативность.
Ну и тупо возвращать 'true' — это тоже плохо. Так как срубает
возможность класть объекты в hash-контейнеры.
Здравствуйте, nikov, Вы писали:
C>>В этом случае лучше кинуть NullReferenceException — чтобы сохранить C>>коммутативность. N>Существует мнение, что вручную бросать NullReferenceException — строго неправильно.
Почему?
Здравствуйте, Cyberax, Вы писали:
C>>>В этом случае лучше кинуть NullReferenceException — чтобы сохранить C>>>коммутативность. N>>Существует мнение, что вручную бросать NullReferenceException — строго неправильно. C>Почему?
Здравствуйте, nikov, Вы писали:
C>>В этом случае лучше кинуть NullReferenceException — чтобы сохранить C>>коммутативность.
N>Существует мнение, что вручную бросать NullReferenceException — строго неправильно.
+1, хотя майкрософт иногда даже в документации говорит, что, мол, "метод бросает NullReferenceException" (например, здесь [справедливости ради, описываемого поведения не наблюдается ])
Help will always be given at Hogwarts to those who ask for it.
nikov wrote: > C>>>В этом случае лучше кинуть NullReferenceException — чтобы сохранить > C>>>коммутативность. > N>>Существует мнение, что вручную бросать NullReferenceException — > строго неправильно. > C>Почему? > Потому что для этой цели существует ArgumentNullException.
В данном случае лучше NullReferenceException, чтобы метод Equals
сохранял коммутативность:
String a="aadfafasf";
String b=null;
b.equals(a); //<--- NullPointerException
a.equals(b); //<--- А почему тогда тут не оно?!
C>>String a="aadfafasf";
C>>String b=null;
C>>b.equals(a); //<--- NullPointerException
C>>a.equals(b); //<--- А почему тогда тут не оно?!
C>>
N>Потому что в последней строке я не пытаюсь вызвать метод у null-ссылки.
Дело в том, что, по идее, отношение эквивалентности должно быть рефлексивным, симметричным и транзитивным. Разные типы выбрасываемых исключений симметричность нарушают.
Так что идеологически у NullReferenceException тоже есть преимущество.
nikov wrote: > N>>Потому что в последней строке я не пытаюсь вызвать метод у null-ссылки. > C>Дело в том, что, по идее, отношение эквивалентности должно быть > рефлексивным, симметричным и транзитивным. Разные типы выбрасываемых > исключений симметричность нарушают. > Тут я мог бы возразить, что в первой строке до вызова метода, > реализующего отношение эквивалентности, дело не доходит.
А я бы мог начать долгий терминологический флейм по поводу того, то
считать вызовом метода
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, _d_m_, Вы писали: ___>>Еще один "не читал, но осуждаю". S>О, спасибо. Я как раз это и искал. S>Все, кроме вот этого комментария можно опустить: ___>> // Т.к. в System.Object не определены поля, следует считать, что поля равны ___>> return true; S>Как я и говорил, это приведет к тому, что если не переопределить Equals в наследнике Object, то унаследованная реализация вернет true для любой пары объектов.
Ну ведь справедливо, что Object.Equals так работает. По хорошему, чтобы метод Object.Equals работал для наследников корректно — надо использовать отражение для сравнения значений полей.
Здравствуйте, _d_m_, Вы писали: ___>Ну ведь справедливо, что Object.Equals так работает.
Ничего справедливого я тут не вижу. Более-менее приемлемой была бы вот такая реализация:
public class Object {
public virtual Boolean Equals(Object obj) {
if( obj == null ) return false;
if ((this.GetType() == typeof(object)) && obj.GetType() == typeof(object)) return true;
}
}
Но ее полезность кажется мне весьма сомнительной. Кроме всего прочего, она не дает использовать экзотический сценарий пустого объекта-маркера, когда мы можем получить гарантированно уникальный тег, просто выполнив new object(). ___>По хорошему, чтобы метод Object.Equals работал для наследников корректно — надо использовать отражение для сравнения значений полей.
Во-первых, Рихтер предложил не это.
Во-вторых, ничего особенно хорошего из этого тоже не выйдет.
Совершенно не факт, что эквивалентность объектов должна строиться на эквивалентности их мемберов. Это — value-type семантика, поэтому именно такая реализация выбрана для value типов. Для reference-type семантики (а она встречается скорее даже чаще, чем value type семантика) как правило эквивалентность совпадает с идентичностью. На пальцах: строка "Иван" взаимозаменяема с любой другой строкой "Иван" (семантика value-типа). Человек по имени Иван в общем случае невзаимозаменяем с любым другим Иваном. Если в данном конкретном случае хочется использовать именно value-type семантику при сравнении объектов, то придется написать это явно.
Кроме того, хочу напомнить, что подобная реализация будет еще и чудовищно дорогой. Предположим, у нас есть вот такой примитивный объект:
public class TreeNode<T>
{
private TreeNode<T> _left;
private TreeNode<T> _right;
private T _data;
}
Публичные мемберы я опускаю по соображениям очевидности. Давайте попробуем найти такой TreeNode<int> node в списке. Предложенная реализация Equals будет вынуждена сделать следующее:
1. Получить через Reflection список всех полей TreeNode<T>
2. Применить попарный Equals ко всем полям по очереди.
3. для _left и _right мы очевидным образом свалимся в рекурсию
Таким образом, нам придется обойти всё дерево. Классно, да? И легким манием руки на битву двинул он полки. И чтобы избавиться от этого спецэффекта, программисту опять же придется перегружать Equals, причем предка при этом вызывать по прежнему нельзя. (Напомню, что Рихтера раздражало как раз то, что прямым наследникам object нельзя вызывать базовый Eauals в своем, а непрямым — нужно.)
Ручная реализация почленного сравнения будет, очевидно, устроена каким-то другим образом.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, _d_m_, Вы писали: ___>Здесь надо сравнивать сами ссылки, а не объекты на которые ссылаются.
Почему? Как ты определишь, для каких мемберов вызывать Equals а для каких ReferenceEquals? В общем случае это сделать невохможно — именно поэтому Рихтер не стал предлагать такую ботву.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, _d_m_, Вы писали:
___>Для меня очевидно как раз другое. Это то, что поиск в List<T> должен использовать не Equals, а ReferenceEquals. Да и для чего существует тогда два метода, которые на самом деле одно и тоже? ___>MSDN: ___>
___>Object.Equals — Determines whether the specified Object is equal to the current Object. (Тогда какого хрена он работает как ReferenceEquals?)
___>Object.ReferenceEquals — Determines whether the specified Object instances are the same instance.
___>Ну так где бред и тяжелая наркомания? Может стоит сначала разобраться, а потом вешать ярлыки?
Sinclair уже говорил про идентичность. Это — свойство объектов в ООП. Только по нему есть смысл сравнивать все объекты, т.к. два объекта с разной идентичностью — это концептуально различные вещи; даже если они обладают одинаковым набором свойств, то это никогда не сложно исправить
С другой стороны, всегда существуют такие вещи, которые проще записывать в функциональном стиле. В ФП рассматриваются не объекты, а значения. Значения не обладают идентичностью, значение полностью определяет само себя. Значение не может быть изменено, можно мутабельной переменной присвоить другое значение. Потому значения сравниваются по содержимому.
В .NET Equals и GetHashCode как раз были соданы для эмуляции того самого поведения значений в ФП. Для объектов с идентичностью не надо переопределять Equals и GetHashCode, для значений — надо. Вот если бы не было значений, то хватило бы одного ReferenceEquals, потому как в этом случае не надо было бы вообще переопределять Equals и GetHashCode.
C>Дело в том, что, по идее, отношение эквивалентности должно быть рефлексивным, симметричным и транзитивным. Разные типы выбрасываемых исключений симметричность нарушают.
Тут где-то был большой флейм о том, что экземплярный Equals полюбому нарушает эти принципы
Здравствуйте, AndrewVK, Вы писали:
AVK>Мало ли что там в CLR можно. Мы говорим о языке C#.
Кстати, продолжим :о)) Всё-таки насколько правильно называть сигнатурой то, что позволяет однозначто выделить метод от других, схожих? Ведь именно по "сигнатуре" компилятор должен определять, какой вызов нужно осуществить в точке вызова?
Как, в таком случае описания исключений, выбрасываемых методом, может быть частью сигнатуры? Вернее даже, зачем их понимать под частью сигнатуры?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Sinclair, Вы писали:
S>>...В свете этого, мне вообше непонятно, зачем в дотнете разрешили сочетать перегрузку Equals/GetHashCode для изменяемых объектов.
VD>Дык в дотнете нет (на мой взгляд, напрасно) понятия неизменяемый тип. Неизменяемые объекты делаются паттерном. Это значит, что рантайм или компилятор ни ухом, ни рылом не знает о том, что объекты некоего типа являются неизменяемыми.
VD>Меж тем введние подобного класса объектов (типов, точнее) было бы очень правильным решением (особенно в виду увеличения функциональщины в мэйнстриме). Такие объекты не только могли бы контролироваться рантаймом и компиляторами, но и могли бы позволить повысить производительность рантайма. Ведь GC с ними мог бы работать по другому. Они не требуют райт-барьена и могут жить в отдельной (более простой и эффективной) куче.
Хотелось бы еще услышать наглядный пример. Т.е. как эти неизвменяемые объекты выглядят на практике?
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, _ks_, Вы писали:
__>>Хотелось бы еще услышать наглядный пример. Т.е. как эти неизвменяемые объекты выглядят на практике?
VD>В смысле? Сроку видел? Вот примерно так же, но из типа было бы сразу ясно, то объект неизменяемый.
Теперь ясно. Спасибо.
ЗЫЖ В слове "Сроку" нехватает после С буквы О, Т, или там А вместо О?
VGn wrote: > C>Дело в том, что, по идее, отношение эквивалентности должно быть > рефлексивным, симметричным и транзитивным. Разные типы выбрасываемых > исключений симметричность нарушают. > Тут где-то был большой флейм о том, что экземплярный Equals полюбому > нарушает эти принципы
Почему? Что имеется в виду под словом "экземплярный"?
Здравствуйте, VladD2, Вы писали:
N>>Интересно, а эти самые неизменяемые объекты могут держать ссылки на изменяемые объекты?
VD>По идее — нет.
Получается, что массив не может быть полем неизменяемого объекта? Или нужен будет ещё и read-only неизменяемый массив?
Или, нарпимер, DataSet — он тоже не может быть полем неизменяемого объекта?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Получается, что массив не может быть полем неизменяемого объекта? Или нужен будет ещё и read-only неизменяемый массив?
Думаю, достаточно будет понятия readonly interface. Но касательно оптимизаций остается еще JIT со skip visibility check и рефлекшен.
Здравствуйте, AndrewVK, Вы писали:
_FR>>Получается, что массив не может быть полем неизменяемого объекта? Или нужен будет ещё и read-only неизменяемый массив?
AVK>Думаю, достаточно будет понятия readonly interface.
Это аналог const-методов в С++? То есть методы декларируют, что неизменяют внутреннего состояния объекта? А должен ли это проверять компилятор? Ведь тогда нельзя будет иметь readonly-события.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали: _FR>Это аналог const-методов в С++? То есть методы декларируют, что неизменяют внутреннего состояния объекта? А должен ли это проверять компилятор?
Нет, не компилятор, а верификатор.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, AndrewVK, Вы писали:
_FR>>А должен ли это проверять компилятор?
AVK>Должен. И не только компилятор, но еще и JIT.
Отлично
_FR>> Ведь тогда нельзя будет иметь readonly-события. AVK>А зачем события в публичном контракте immutable объекта?
Мне казалось, что для immuta-бильности достаточно иметь все поля readonly (в сегодняшнем смысле, то есть константные ссылки, а не ссылки на константы) — ведь именно тогда объект является неизменяемым? А вот являются ли неизменяемыми типы этих полей — их личное дело. Ведь при изменении внутренних данных своего поля объект не меняется. Или я не прав и что-то не знаю\не понимаю?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, VladD2, Вы писали:
VD>По идее — нет.
На самом деле, да. Ведь ссылка на mutable-объект — это как-бы его identity. Если этот самый identity нельзя изменить, то иммутабельность сохраняется. Например, в Nemerle можно написать
controls : list[Control]
При этом список останется иммутабельным, у него будет неизменный хэш-код, и он будет эквивалентен другим спискам, содержащим те же контролы в том же порядке (здесь под "те же" имеется в виду равенство идентичностей, а не содержимого).
Здравствуйте, _FRED_, Вы писали:
_FR>Мне казалось, что для immuta-бильности достаточно иметь все поля readonly (в сегодняшнем смысле, то есть константные ссылки, а не ссылки на константы) — ведь именно тогда объект является неизменяемым?
В случае событий не соблюдается даже это — при подписке или отписке меняется ссылка, а ничего иного снаружи с событием сделать нельзя.
Здравствуйте, AndrewVK, Вы писали:
_FR>>Мне казалось, что для immuta-бильности достаточно иметь все поля readonly (в сегодняшнем смысле, то есть константные ссылки, а не ссылки на константы) — ведь именно тогда объект является неизменяемым?
AVK>В случае событий не соблюдается даже это — при подписке или отписке меняется ссылка, а ничего иного снаружи с событием сделать нельзя.
Можно: через "ручную" реализацию посредством EventHandlerList, например.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, lomeo, Вы писали:
L>Если под иммутабельным объектом понимают ValueObject, то по идее неприватные свойства тоже должны быть иммутабельны. Например, представь значение типа Person со свойством Name мутабельного типа StringBuilder. По моему, если меняется свойство, то и сам объект тоже меняется (в том смысле, что это уже не значение).
Это уже дело объекта вернее, автора его типа ): выбирать тип для его свойств. Для "ключевых" свойств выбирать mutable-тип бессмысленно, а вот для неключевых — может быть.
Кстати, свойства более чем могут быть mutable (в смысле могут быть и get и set), так как это "внешний интерфейс". Immuta-бильность — свойство состояния объекта (которое определяется только набором полей), а не его интерфейса.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Кстати, свойства более чем могут быть mutable (в смысле могут быть и get и set), так как это "внешний интерфейс". Immuta-бильность — свойство состояния объекта (которое определяется только набором полей), а не его интерфейса.
Тогда иммутабельный объект и значение — разные вещи. Извиняюсь.
Здравствуйте, _FRED_, Вы писали:
_FR>Ага! Правильно ли я понянял вас с IT, что эти самые immutable-объекты, которых я не понимаю: эмуляция типов с семантикой значения? Вернее даже не "эмуляция", а новый их аттрибут, который сможет помочь рантайму более производительно обрабытывать эти типы?
Примерно так.
... << RSDN@Home 1.2.0 alpha rev. 717>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IB, Вы писали:
ANS>>Но раз ты так написал, то вопрос, почему так? IB>Я не написал, я процитировал.
Понятно.
ANS>> Чем публичное поле отличается от публичного свойства для пользователя контракта (в смысле для программиста, который пользуется объектом)? IB>Хотя бы метаданными.
Если бы пара гетер/сетер была обязательной, то в этом был бы смысл. А так...
ANS>> Например создаётся событие "свойство такое-то поменялось". IB>Событие — это не побочный эффект.
Неужто? Зачем же нужны события, в ответ на которые никто ничего не делает?
Здравствуйте, Andrei N.Sobchuck, Вы писали:
ANS>Если бы пара гетер/сетер была обязательной, то в этом был бы смысл.
В этом и так есть смысл.
ANS>Неужто?
Ужто.
ANS> Зачем же нужны события, в ответ на которые никто ничего не делает?
В ответ на события делают снаружи объекта, а не внутри оного.
Здравствуйте, _FRED_, Вы писали:
_FR>Получается, что массив не может быть полем неизменяемого объекта? Или нужен будет ещё и read-only неизменяемый массив?
Если вводить неизменяемость на уровне рантайма, то все базовые структуры обязаны иметь неизменяемые варианты.
_FR>Или, нарпимер, DataSet — он тоже не может быть полем неизменяемого объекта?
Не может.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, konsoletyper, Вы писали:
VD>>По идее — нет.
K>На самом деле, да. Ведь ссылка на mutable-объект — это как-бы его identity. Если этот самый identity нельзя изменить, то иммутабельность сохраняется. Например, в Nemerle можно написать
K>
K>controls : list[Control]
K>
K>При этом список останется иммутабельным, у него будет неизменный хэш-код, и он будет эквивалентен другим спискам, содержащим те же контролы в том же порядке (здесь под "те же" имеется в виду равенство идентичностей, а не содержимого).
Это разные вещи. То о чем говоришь ты уже есть и для этого ничего не надо делать. А вот неизменяемые объекты — это немного другое дело.
Бло бы здорово если компилятор бы автоматом проверял бы вложенность и не позволял бы хранить в неизменяемых объектах списки изменяемых, но позволял бы хранить списки неизменяемых.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, _d_m_, Вы писали:
___>Поэтому Microsoft должна была реализовать метод Equals типа Object так: ___>
___>public class Object {
___> public virtual Boolean Equals(Object obj) {
___> if( obj == null ) return false;
___> if( this.GetType() != obj.GetType() ) return false;
___> // Т.к. в System.Object не определены поля, следует считать, что поля равны
___> return true;
___> }
___>}
___>
___>... ___>[/q]
Согласен с Синклером. Заявление мягко говоря опрометчивое. По фигу что "в System.Object не определены поля". Ведь метод автоматически наследуется всеми потомками! Это приведет к тому, что всенаследники по умолчанидю получат некорректную реализацию этого метода. А это уже натуральная деверсия.
Сейчас реализация рассчитана на то, что по умолчанию объекткт опеределяется его ссылкой. Разные ссылки == разные объекты. Такое поведение приемлемо для большинства применений (что и показывает практика). Если это поведение неприемлемо, то нужно просто переопределять его.
Так что на мой взгляд Риктер неправ.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, IB, Вы писали:
ANS>> Зачем же нужны события, в ответ на которые никто ничего не делает? IB>В ответ на события делают снаружи объекта, а не внутри оного.
Аа. Изменение состояния не объекта, но всей системы делает эффект не побочным? Понимаю...
Здравствуйте, _FRED_, Вы писали:
_FR>Да, спасибо. AndrewVK c IT уже мне всё объяснили.
_FR>Я понимал под "неизменяемостью" немного другое: запрет на изменение полей класса.
Объекта наверное... А что в нем еще что-то можно менять?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
_FR>>Я понимал под "неизменяемостью" немного другое: запрет на изменение полей класса. VD>Объекта наверное...
Конечно
VD>А что в нем еще что-то можно менять?
class A
{
public object b;
}
class X
{
A a = new A();
static void Main() {
X x = new X();
x.a.b = "aaa"; // здесь поле 'a' объекта 'x' не меняется, а меняется поле 'b' объекта 'x.a'
x.a = new A(); // а вот тут меняется поле 'a' объекта 'x'
}
}
Другими словами, я называл "неизменяемым" тип, все поля которого являются "readonly" (в терминах C#), без ограничения того, что типы полей такого типа так же должны быть "неизменяемыми".
... << RSDN@Home 1.2.0 alpha rev. 717>>
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _d_m_, Вы писали:
___>Ага, я решил в своем проекте использовать сборку Васи Пупкина. Где гарантия, что он их использовал по назначению? Уж если даже в самой FCL они не всегда по назначению. Это как с управлением памятью в C/C++ — надо просто ее всегда ее освобождать. Но... не всегда получалось — и память текла. И тогда подумали и сделали .Net и в нем GC. Чуствуешь взаимосвязь?
Если использовать в своих проектах черт-знает-что от черт-знает-кого, то результат будет понятно какой.
Связь между пропертями и управлением памятью не чувстствую...
Здравствуйте, _d_m_, Вы писали:
HB>>А где гарантия, что Вася, например, не написал метод get_Something(), который меняет состояние объекта? ___>Гарантии нет, но: ___>
___>...
___> MyClass c = new MyClass();
___> int d = c.I; // то, что здесь меняется состояние объекта "c" уж очень неочевидно
___> int e = c.get_I();
___>...
___>
Если честно, мне это в обоих случаях не очевидно — меняется оно или нет. Но если клиент должен немедленно реагировать на изменение состояния, то в C# это будет событие. В какую из пар фигурных скобочек при этом заключен код, изменивший состояние, а равно как и то, что перед этими скобочками написано (get, set, get_I() или ещё что) — совершенно не важно.
Здравствуйте, VladD2, Вы писали:
VD>Бло бы здорово если компилятор бы автоматом проверял бы вложенность и не позволял бы хранить в неизменяемых объектах списки изменяемых, но позволял бы хранить списки неизменяемых.
Ещё одно полезное применение неизменяемости это covariant generic parameters — неизменяемые типы дают статическую гарантию безопасности этой фичи.
А то я уже задолбался yield return писать.
Здравствуйте, EvilChild, Вы писали:
EC>Здравствуйте, VladD2, Вы писали:
VD>>Бло бы здорово если компилятор бы автоматом проверял бы вложенность и не позволял бы хранить в неизменяемых объектах списки изменяемых, но позволял бы хранить списки неизменяемых. EC>Ещё одно полезное применение неизменяемости это covariant generic parameters — неизменяемые типы дают статическую гарантию безопасности этой фичи. EC>А то я уже задолбался yield return писать.
Можете по подробней описать, при чем тут yield return?
Здравствуйте, Kore Sar, Вы писали:
EC>>Ещё одно полезное применение неизменяемости это covariant generic parameters — неизменяемые типы дают статическую гарантию безопасности этой фичи. EC>>А то я уже задолбался yield return писать.
KS>Можете по подробней описать, при чем тут yield return?
Например есть IEnumerable<string>, надо вернуть IEnumerable<object>.
Тупо return значение типа IEnumerable<string> из функции с типом возвращаемого значения IEnumerable<object> не прокатит.
Вот yield return единственный известный мне выход.
now playing: Marc Antona & Anthony Collins — AM-PM
Здравствуйте, _d_m_, Вы писали:
___>И что же такого хорошего в этих пропетях? По моему так без них только лучше.
Все сообщения этой темы ниасилил. Не знаю, может кто-нить уже упоминал об этом. Самое главное достоинство пропертей — это то, что их семантика идеально подходит для различных визуальных сред программирования, свойства объектов которых радактируются в проперти-гридах. Скрытие чтение и записи под одним именем свойства позволяет одновременно видеть значение свойства в проперти-гриде и при необходимости изменять его:
*-----------*------------*
| Caption | Window cap |
*-----------*------------*
| Left | 253 |
*-----------*------------*
Представим себе, что мы бы отказались от пропертей. Тогда таблица свойств объекта получилась бы примерно такой:
Здравствуйте, EvilChild, Вы писали:
EC>Здравствуйте, Kore Sar, Вы писали:
EC>>>Ещё одно полезное применение неизменяемости это covariant generic parameters — неизменяемые типы дают статическую гарантию безопасности этой фичи. EC>>>А то я уже задолбался yield return писать.
KS>>Можете по подробней описать, при чем тут yield return?
EC>Например есть IEnumerable<string>, надо вернуть IEnumerable<object>. EC>Тупо return значение типа IEnumerable<string> из функции с типом возвращаемого значения IEnumerable<object> не прокатит. EC>Вот yield return единственный известный мне выход.
Здравствуйте, ArtDenis, Вы писали:
AD>Представим себе, что мы бы отказались от пропертей. Тогда таблица свойств объекта получилась бы примерно такой: AD>
Здравствуйте, EvilChild, Вы писали:
EC>Здравствуйте, Kore Sar, Вы писали:
KS>>А преобразовать к необходимому типу? EC>Можешь привести пример рабочего кода?
Здравствуйте, AndrewVK, Вы писали:
AVK>Достаточно один раз написать. AVK>
AVK>IEnumerable<T> Cast<T>(IEnumerable src) where T : class
AVK>{
AVK> foreach (object item in src)
AVK> yield return (T)item;
AVK> // Вариант:
AVK> // T typedItem = item as T;
AVK> // if (item != null)
AVK> // yield return (T)item;
AVK>}
AVK>
AVK>В linq2objects что то подобное есть ввиде extension method.
То, о чём я говорил прямо противоположно приведённому тобой коду. Но это не принципиально.
AVK>А вобще необходимость подобных финтов, да еще и в большом количестве это повод задуматься.
Задуматься о чём?
Ты как решаешь проблему отсутствия константности в .NET? Или у тебя нет такой проблемы?
Здравствуйте, EvilChild, Вы писали:
EC>То, о чём я говорил прямо противоположно приведённому тобой коду.
А если присмотреться повнимательнее?
AVK>>А вобще необходимость подобных финтов, да еще и в большом количестве это повод задуматься. EC>Задуматься о чём?
О дизайне.
EC>Ты как решаешь проблему отсутствия константности в .NET?
При чем тут константность? Речь о ковариантности дженериков по type parameter.
Здравствуйте, _FRED_, Вы писали:
_FR>К тому же твой пример ещё и не скомпилится ;о)
Ты пробовал? Каким компилятором?
Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.42 компилит мой код на ура.
Здравствуйте, AndrewVK, Вы писали:
EC>>Именно для этого случая мне понадобилась ковариантность, причём она здесь совершенно безопасна.
AVK>Не совсем так. Readonly недостаточно для безопасности ковариантности, нужно еще отсутствие параметров методов с типами из type arguments.
В моём случае (применительно к возвращаемому значению) безопасна.
По поводу методов согласен.
Твоё замечание относительно дизайна после моего уточнения остаётся в силе?
Если да, то можешь пояснить, что именно не нравится?
Здравствуйте, EvilChild, Вы писали:
EC>Твоё замечание относительно дизайна после моего уточнения остаётся в силе? EC>Если да, то можешь пояснить, что именно не нравится?
Лучше сделать элементы immutable на самом деле, а не за счет одного из интерфейсов.
Здравствуйте, _FRED_, Вы писали:
_FR>Так как IEnumerable<TInput> "унаследован" от IEnumerable, то версия AndrewVK "общее" и полностью покрывает твою. Проверь
Есть ещё одно отличие, на мой взгляд принципиальное в контексте обсуждаемой фичи.
Код Андрея более универсален и позволяет делать как upcast, так и downcast,
мой же только upcast, что даёт статическую гарантию успешного приведения, т.е. делает ровно то,
что от него требуется для решения этой задачи и его сложнее использовать неправильно.
Даже если ты перепутаешь порядок типов при вызове функции, то компилятор тебе об этом сообщит.
В общем при помещении этого кода в библиотеку я бы сделал 2 функции StaticCast & DynamicCast.
Здравствуйте, AndrewVK, Вы писали:
_FR>>Так как IEnumerable<TInput> "унаследован" от IEnumerable, то версия AndrewVK "общее" и полностью покрывает твою. Проверь
AVK>Не совсем. Там есть еще констрейнт.
Здравствуйте, EvilChild, Вы писали:
EC>Здравствуйте, mogadanez, Вы писали:
M>>а мы проперти с маленькой буквы пишем вот_так_вот EC>Ужас какой. Не диссонирует с библиотечным кодом?
В этом есть офигенный плюс как раз....
видно где наш код где ВасиПупкина...
на_фоне_нашего кода ПрыгающийКодВасиПупкина выглядит как ахтунг
Здравствуйте, mogadanez, Вы писали:
M>В этом есть офигенный плюс как раз.... M>видно где наш код где ВасиПупкина... M>на_фоне_нашего кода ПрыгающийКодВасиПупкина выглядит как ахтунг
А то, что ВесьОстальнойКодВключаяФреймворковский так выглядит, не приводит к ложным срабатываниям на ахтунг?
Мне подобная мешанина глаза царапала ещё во времена микса ATL & STL.
now playing: Marc Antona & Anthony Collins — AM-PM
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, _FRED_, Вы писали:
_FR>>Что произойдёт при попытке вызова моей программой метода A?
AVK>Будет джавовский аналог исключения "Член не найден" при загрузке класса.
Как то превратно звучит .
Побеждающий других — силен,
Побеждающий себя — Могущественен.
Лао Цзы
Здравствуйте, AndrewVK, Вы писали:
_FR>>Так как IEnumerable<TInput> "унаследован" от IEnumerable, то версия AndrewVK "общее" и полностью покрывает твою. Проверь
AVK>Не совсем. Там есть еще констрейнт.
Ага, не знаметил, виноват
... << RSDN@Home 1.2.0 alpha rev. 717>>
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, EvilChild, Вы писали:
_FR>>К тому же твой пример ещё и не скомпилится ;о) EC>Ты пробовал? Каким компилятором? EC>Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.42 компилит мой код на ура.
Извини, не заметил констрэйнт
... << RSDN@Home 1.2.0 alpha rev. 717>>
Help will always be given at Hogwarts to those who ask for it.
EC>А то, что ВесьОстальнойКодВключаяФреймворковский так выглядит, не приводит к ложным срабатываниям на ахтунг? EC>Мне подобная мешанина глаза царапала ещё во времена микса ATL & STL.
Здравствуйте, EvilChild, Вы писали:
_FR>>К тому же твой пример ещё и не скомпилится ;о) EC>Ты пробовал? Каким компилятором? EC>Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.42 компилит мой код на ура.
Меня сбило с толку приведение типов в твоём коде здесь:
yield return(TOutput)item;
которое абсолютно не нужно.
С констрэйнтом да, твой код значительно отличается от кода AndrewVK (вернее, кода "стандартного" класса Enumerable нового ("будущего"?) Framework 3.5)
... << RSDN@Home 1.2.0 alpha rev. 717>>
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, AndrewVK, Вы писали:
AVK>У тебя констрейнт.
Я не понял, что ты гоыворишь о моём коде.
Вопрос был зачем в твоём коде констрейнт (where T : class)?
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, mogadanez, Вы писали:
M>>не попробуешь, не узнаешь, мы попробовали — нам понравилось. M>>через _ логические части имени разделяются лучше чем при заглавной букве. WH>ИМХО без разници. WH>Но вы отступили от общепринятого стандарта что есть плохо.
плохо кому? у нас от этого только повышение эффективности... так что нам хорошо
Здравствуйте, mogadanez, Вы писали:
M>плохо кому?
Тому кто с этим кодом будет работать.
M>у нас от этого только повышение эффективности... так что нам хорошо
Как измеряли?
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, mogadanez, Вы писали:
M>>плохо кому? WH>Тому кто с этим кодом будет работать.
МЫ
M>>у нас от этого только повышение эффективности... так что нам хорошо WH>Как измеряли?
субъективно конечно. мне такой код воспринимать _легче_, а значит я с ним работаю эффективнее. я вижу где код свой а где чужой, и знаю что я могу изменить и что нет, не прикладывая _никаких_ усилий.
Здравствуйте, mogadanez, Вы писали:
M>>>плохо кому? WH>>Тому кто с этим кодом будет работать.
M>МЫ
Если вы не собираетесь менять состав команды на протяжении всей жизни проекта — то ладно, но таким мало кто может похвастать. В условиях же, когда "окружение" может меняться общие и единые стандарты — именно то средство, которое позволит изменениям "притереться" друг к другу с наименьшими проблемами. Во
Хотя, читать ваши исходники совсем не плохо, но это настолько отходит от общепринятых норм…
... << RSDN@Home 1.2.0 alpha rev. 717>>
Help will always be given at Hogwarts to those who ask for it.
К ним есть где придраться — те же "overrid" на самом деле не просечёшь же Так что далеко не весть "свой" код можно отличить от "чужого". Во-вторых, после года плотной и упорной работы практически с любой библиотекой можно [по-памяти] сказать, какой код "их", а какой "наш".
Ну, и последнее, самое, ИМХО, существенное: если хоть одна какая-то сторонняя контора, библиотеки которой вы используете у себя, решит принять такой же code-style, как и вы, от декларируемых вами преимуществ не останется и следа, правильно я понимаю? так как нельзя будет на основании одного имени класса\метода\свойства сделать различие?
... << RSDN@Home 1.2.0 alpha rev. 717>>
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, mogadanez, Вы писали:
M>>вот мнение человека об этом недавно пришедшего в команду. на момент поста — ~месяц
M>>http://kuklaora.blogspot.com/2007/04/naming-conventions.html
_FR>К ним есть где придраться — те же "overrid" на самом деле не просечёшь же Так что далеко не весть "свой" код можно отличить от "чужого". Во-вторых, после года плотной и упорной работы практически с любой библиотекой можно [по-памяти] сказать, какой код "их", а какой "наш".
ну это не мой пост =)
про чужую библиотеку...
иногда нужно назвать библиотеку также как и системная например.
HttpUtility. нам проще, не надо ничего делать. она будет просто http_utility. иначе нужно было бы ее называть по другому, или использовать имя с неймспейсом или в юзинг алиас писать
_FR>Ну, и последнее, самое, ИМХО, существенное: если хоть одна какая-то сторонняя контора, библиотеки которой вы используете у себя, решит принять такой же code-style, как и вы, от декларируемых вами преимуществ не останется и следа, правильно я понимаю? так как нельзя будет на основании одного имени класса\метода\свойства сделать различие?
это просто доп. бенефит который мы заметили, используя такое именование. мне просто больше_нравится_читать_такой код ЧемТакойКод. _лучше_разделены_куски_