Re[11]: Багодром: Реализация операторов сравнения
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.04.08 13:22
Оценка: 3 (1)
Здравствуйте, s.and, Вы писали:

SA>Э нет... Не отстану. По причинам:...


Расслабьтесь, уважаемые господа!

Что вы устроили ругань на пустом месте? По поводу твоего вопроса я отвечу сам. Собственно уже ответил
Автор: VladD2
Дата: 03.04.08
. К вопросу Kore Sar он не имеет никакого отношения. Kore Sar совершенно верно нашел опечатку и указал на нее.

По поводу твоего замечания наверно стоило бы добавить комментарий, но не уверен, что столь примитивные вопросы имеет смысл обсасывать в статье посвященной другим.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Багодром: Реализация операторов сравнения
От: eugen1001  
Дата: 03.04.08 14:14
Оценка:
Здравствуйте, s.and, Вы писали:

E>>А не проще сразу IsNull(object)?


SA>Метод
public static bool object.IsNull(object obj)
не определен...


Я хотел сказать, что было бы грамотней такой метод создать, и требовать его использование (или предупреждать) вместо конструкции
obj == null
... << RSDN@Home 1.2.0 alpha rev. 775>>
Re[4]: Багодром: Реализация операторов сравнения
От: Powerz Россия https://zagosk.in
Дата: 03.04.08 15:07
Оценка:
Здравствуйте, s.and, Вы писали:

SA>А можно ссылку на статью об "as"?


As is или история о том как не надо писать код
Автор(ы): Владислав Чистяков (VladD2)
Дата: 18.12.2004
Работая над открытыми проектами, автор заметил, что операторы as и is многими программистами зачастую используются ненадлежащим образом. Результатом очередного двухчасового поиска ошибки и стала эта статья.


... << RSDN@Home 1.2.0 alpha rev. 784>>
https://zagosk.in
Re[5]: Багодром: Реализация операторов сравнения
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.04.08 15:35
Оценка:
Здравствуйте, Lloyd, Вы писали:

KS>>Влад, мы тут организовываем секту "Свидетей Влада".


L>Это ты про себя "мы"?


Их уже двое: http://rsdn.ru/forum/message/2901802.1.aspx
Автор: SiAVoL
Дата: 03.04.08
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Багодром: Реализация операторов сравнения
От: Mika Soukhov Stock#
Дата: 03.04.08 19:04
Оценка: 42 (1) +1 :))) :))
Здравствуйте, Kore Sar, Вы писали:

KS>О Влад! Вы здесь!


KS>Влад, мы тут организовываем секту "Свидетей Влада". Вы не против?


Только под землю не зарывайтесь.
Re[3]: Багодром: Реализация операторов сравнения
От: _FRED_ Черногория
Дата: 03.04.08 21:04
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>... и за одно приведет к верному результату — CompareTo возвратит -1.


Реализация IComparable должна выбрасывать исключение, если сравниваемые типы "несовместимы":

The parameter, obj, must be the same type as the class or value type that implements this interface; otherwise, an ArgumentException is thrown.

здесь.

Почему у тебя -1? Просто что б поддержать сортировку несовместимых типов? Для этого мне кажется более правильно иметь сторонний, специальный IComparer который должен бросать ArgumentException при:

x and y are of different types and neither one can handle comparisons with the other.


(здесь)
... << RSDN@Home 1.2.0 alpha 4 rev. 1048>>
Help will always be given at Hogwarts to those who ask for it.
Re[4]: Багодром: Реализация операторов сравнения
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.04.08 09:03
Оценка: 2 (2)
Здравствуйте, _FRED_, Вы писали:

_FR>Реализация IComparable должна выбрасывать исключение, если сравниваемые типы "несовместимы":

_FR>

_FR>The parameter, obj, must be the same type as the class or value type that implements this interface; otherwise, an ArgumentException is thrown.

_FR>здесь.

_FR>Почему у тебя -1? Просто что б поддержать сортировку несовместимых типов?


На этот вопрос есть два ответа. Вопервых такая логика была в исходном коде (коде который и содержал ошибку). Мне банально было не до этой мелочи. Можно сказать — увлекся.

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

_FR>Для этого мне кажется более правильно иметь сторонний, специальный IComparer который должен бросать ArgumentException при:

_FR>

x and y are of different types and neither one can handle comparisons with the other.


_FR>(здесь)

Любой паттерн или правило нужно выполнять с умом. И не выполнять его если выполнение может привести к проблемам большим нежели та что может случиться в случае его не выполнения.

Суть этого совета/паттерна заключается в том, что такой подход позволяет быстрее выявлять ошибки в коде. Но тут нужно учитывать то, что сортированность не так критична, а вот полная неработоспособность в следствии исключений генерируемых в процессе сортировки крайне нежелательна.

Если спросить меня как бы я поступил в реальном коде, то я бы ответил, что просто выбросил всю эту ахинею, стал использовать в комбобоксах реальные типы, а сортировку реализовал с использованием передаваемой лябды-компоратора:
list.Sort((m1, m2) => string.Compare(m1.Name, m2.Name));

http://nemerle.org/svn/vs-plugin/trunk/Nemerle.VisualStudio/LanguageService/NemerleTypeAndMemberDropdownBars.cs
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Багодром: Реализация операторов сравнения
От: _FRED_ Черногория
Дата: 04.04.08 09:12
Оценка:
Здравствуйте, VladD2, Вы писали:
_FR>>Почему у тебя -1? Просто что б поддержать сортировку несовместимых типов?

VD>На этот вопрос есть два ответа. Вопервых такая логика была в исходном коде (коде который и содержал ошибку).


Извини, не видел статьи полностью и не понял, что это просто "калька" от тех самых говриков, которых ты ругаешь Подумал, мало ли ты говоришь о том, как нужно реализовывать, вдобавок к "==" и "!=", операторы сравнения.
... << RSDN@Home 1 alpha 3 rev. 0>>
Help will always be given at Hogwarts to those who ask for it.
Re: Багодром: Реализация операторов сравнения
От: alexanderfedin США http://alexander-fedin.pixels.com/
Дата: 07.04.08 07:53
Оценка:
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

ЧВV>Данная статья посвящена вопросу грамотной реализации операторов сравнения. При кажущейся простоте, эта задача несет в себе ряд скрытых трудностей. Реализация операторов сравнения нередко приводит к появлению неприятных ошибок. В основном эта информация касается C#-программистов, но будет полезна тем, кто пишет .NET-код и на других языках.


Влад, Вы наивный человек. Вы заглянули в код и обнаружили баг — хорошо. Вы посчитали, что код не был протестирован? Скорее всего всё было протестировано, но баг был признан незначительным. А каково тестеру воевать с девелоперами, которые просто разработали спецификацию без оглядки на какие-либо стандарты (пример — Windows Imaging на MSDN online) Здесь в большинстве компаний (не только в Майкрософт) работает огромное количество людей, абсолютное большинство из которых малограмотны, но, благодаря долгому трудовому прошлому в компании, имеют возможность диктовать условия другим. И были и есть и будут есть люди, которые могли бы и хотели бы что-то изменить в лучшую сторону, но биться головой об стену очень больно и трудно, поэтому они забивают на всё огромный болт и становятся такими же — им интересны ежегодные повышения зарплаты, годовые бонусы, количество акций компании, получаемых опять-таки ежегодно. И они продолжают воспитывать уже себе "достойную смену". И это как снежный ком. Вот так-то...
Respectfully,
Alexander Fedin.
Re[2]: Багодром: Реализация операторов сравнения
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.04.08 10:51
Оценка: +1
Здравствуйте, alexanderfedin, Вы писали:

A>Влад, Вы наивный человек. Вы заглянули в код и обнаружили баг — хорошо. Вы посчитали, что код не был протестирован? Скорее всего всё было протестировано, но баг был признан незначительным.


Я не очень наивен. Откровенно говоря баги конкретного (причем неизвестного мене) человека меня мало интересуют. Я привел реальный пример распространенной ошибки.

Что же касается "Скорее всего всё было протестировано, но баг был признан незначительным.", то это и есть наивность. Любой тест привел бы к переполнению стека, что вряд ли можно было не заметить, и уж тем более признать незначительным.

A>А каково тестеру воевать с девелоперами, которые просто разработали спецификацию без оглядки на какие-либо стандарты (пример — Windows Imaging на MSDN online) Здесь в большинстве компаний (не только в Майкрософт) работает огромное количество людей, абсолютное большинство из которых малограмотны, но, благодаря долгому трудовому прошлому в компании, имеют возможность диктовать условия другим. И были и есть и будут есть люди, которые могли бы и хотели бы что-то изменить в лучшую сторону, но биться головой об стену очень больно и трудно, поэтому они забивают на всё огромный болт и становятся такими же — им интересны ежегодные повышения зарплаты, годовые бонусы, количество акций компании, получаемых опять-таки ежегодно. И они продолжают воспитывать уже себе "достойную смену". И это как снежный ком. Вот так-то...


Понятно, хотя и печально. Но это проблема не программистов, а компаний. Точнее их руководства. Мне кажется, что есть ряд задач которые лучше решаются компактной группой высокопроффесиональных спецов, а не гурьбой малоквалифицированных кадров лихо закидывающих буденовками неприятеля. На мой взгляд разработка компиляторов и интеграции языков с IDE как раз такой случай. Уверен, что в МС работает масса отличных спецов которые и двигают компанию вперед. Более того данная статья ни в коем разе не наезд на МС. Это просто иллюстрация которая не только попалась под руку, но и изрядно потрепала нервы. Наверно, надо было вместо конкретных исходников и компании сказать что-то размытое и обтекаемое, но мне показалось, что реальный пример из реальной жизни будет убедительнее. Ведь цель предотвратить подобные вещи в будущем. Точнее уменьшить их число.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Багодром: Реализация операторов сравнения
От: _FRED_ Черногория
Дата: 09.04.08 00:52
Оценка:
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

ЧВV>Статья:

ЧВV>Багодром: Реализация операторов сравнения
Автор(ы): Чистяков Влад (VladD2)
Дата: 15.03.2008
Данная статья посвящена вопросу грамотной реализации операторов сравнения. При кажущейся простоте, эта задача несет в себе ряд скрытых трудностей. Реализация операторов сравнения нередко приводит к появлению неприятных ошибок. В основном эта информация касается C#-программистов, но будет полезна тем, кто пишет .NET-код и на других языках.


Перечитал полную версию статьи и подумалось, что грабли где-то не там, куда нам показывают. Реализация операторов сравнения (и переопределение Equals\GetHashCode) у полиморфных типов — вообще, по-моему, идея сомнительная (В философии не мало об этом говорилось, желающие найдут). Грабли всплывут если не в реализации, то в семантике.

Я бы посоветовал вообще никогда не реализовывать Equals\GetHashCode и соответствующих операторов сравнения в типах, если тип не struct или не sealed class : object в понимании C#. Потому что тогда однозначного ответа о том, что же делает оператор сравнения, без изучения документации или кода дать невозможно: уж слишком по-разному могут обрабатываться отношения между наследуемыми типами в различных ситуациях различными програмистами.

Не могу спорить: реализовать "как-то правильно" Equals\GetHashCode в таких ситуациях можно. Но это будет неочевидно и, скорее всего, не понятно без подробного изучения деталей.

Я бы рекомендовал для сравнения полиморфных типов создавать отдельные компараторы (реализации IEqualityComparer<>). В таком варианте можно будет в одном случае сравникать объекты "так", а в другом — иначе.
... << RSDN@Home 1.2.0 alpha 4 rev. 1048>>
Help will always be given at Hogwarts to those who ask for it.
Re[2]: Багодром: Реализация операторов сравнения
От: _FRED_ Черногория
Дата: 09.04.08 03:02
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Не могу спорить: реализовать "как-то правильно" Equals\GetHashCode в таких ситуациях можно. Но это будет неочевидно и, скорее всего, не понятно без подробного изучения деталей.


В случае необходимости реализовать сравнение в иерархии объектов, надо сделать так:
  // В типе (ThisType), который первый в иерархии будет реализовывать 
  // пользовательский механизм сравнения, переопределить...
  protected sealed override bool Equals(object obj) {
    if(ReferenceEquals(this, obj)) {
      return true;
    } else if(ReferenceEquals(obj, null) || obj.GetType() != GetType()) {
      return false;
    }//if
    return EqualsCore(obj);
  }
  
  // ...и добавить метод
  protected virtual void EqualsCore(object obj) {
    if(obj == null) { // Эта проверка должна осуществляться перед вызовом данного метода.
      throw new ArgumentNullException("obj");
    }//if
 
    ThisType other = (ThisType)obj; // И эта проверка тоже
    return /* реализация сравнения полей this и other */;
  }
  
  // Операторы сравнения определяются так, как в статье
  public static bool operator ==(ThisType left, ThisType right) {
    if(ReferenceEquals(left, right)) {
      return true;
    } else if(ReferenceEquals(left, null)) { // Внимание: проверки типа здесь быть не должно!
      return false;
    }//if
    return left.Equals(right);
  }

  public static bool operator ==(ThisType left, ThisType right) {
    return !(left == right);
  }

  // Так же не плохо бы совсем реализовать IEquatable<ThisType>:
  public bool Equals(ThisType other) {
    if(ReferenceEquals(this, other)) {
      return true;
    } else if(ReferenceEquals(other, null) || other.GetType() != GetType()) {
      return false;
    }//if
    return EqualsCore(obj);
  }

В каждом же наследнике:
  protected override void EqualsCore(object obj) {
    if(obj == null) { // Эта проверка должна осуществляться перед вызовом данного метода.
      throw new ArgumentNullException("obj");
    }//if
    
    if(!base.EqualsCore(obj)) {
      return false;
    }//if

    ThisDerivedType other = (ThisDerivedType)obj; // И эта проверка тоже
    return /* реализация сравнения полей this и other */;
  }
  
  // Операторы сравнения заново, для ThisDerivedType, определяются так, как в статье
  
  // Реализация IEquatable<ThisDerivedType> аналогична предложенной в базовом классе:
  public bool Equals(ThisDerivedType other) {
    if(ReferenceEquals(this, other)) {
      return true;
    } else if(ReferenceEquals(other, null) || other.GetType() != GetType()) {
      return false;
    }//if
    return EqualsCore(obj);
  }


Пару слов об условии
|| obj.GetType() != GetType()

Да, иногда может потребоваться такое сравнение, которое работало бы полиморфно. Но я бы рекомендовал его делать в отдельном IEqualityComparer<>-е, например, по той причине, что при переопределении Equals(object) требуется так же переопределить GetHashCode(), причём так, что бы для объектов, для который Equals вернул true, GetHashCode возвращал бы одинаковые значения. Добиться этого зачастую попросту невозможно: код другого типа вам может быть и не доступен. В стороннем же IEqualityComparer<>-е это как-то, но можно будет решить и для вашего типа, и для чужого.
... << RSDN@Home 1.2.0 alpha 4 rev. 1048>>
Help will always be given at Hogwarts to those who ask for it.
Re[3]: Багодром: Реализация операторов сравнения
От: s.and  
Дата: 09.04.08 05:05
Оценка:
Подписываюсь под каждым словом.
Тоже думалось применимости Equals/GetHashCode/== только к struct и sealed class,
а также о необходимости o1.GetType() == o2.GetType() (у Рихтера об этом еще написано).

Кстати, микрософтовские реализации Equals (за исключением ValueType) и примеры в MSDN вместо o1.GetType() == o2.GetType() используют as с проверкой на null или is. В результате не выполняется микрософтовское же условие x.Equals(y) == y.Equals(x).
Re[2]: Багодром: Реализация операторов сравнения
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.04.08 13:55
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Я бы посоветовал вообще никогда не реализовывать Equals\GetHashCode и соответствующих операторов сравнения в типах, если тип не struct или не sealed class : object в понимании C#.


На мой взгляд, советы тут не уместны. Equals\GetHashCode есть и используются довольно часто. Так что если хочется, чтобы объекты вели себя как надо в стандартных коллекциях и т.п., то прийдется их реализовывать.

Что же касается отдельных копораторов, то на мой взгляд во многих случаях случаев и они не нужны. Скажем, для той же сортировки (ради которой и были реализованы все эти методы) лучше использовать функцию получающую лябду-компаратор. Создать ее для конкретного случая не проблема. Это аналогично заданию order by в SQL-запросе. А объект-компоратор тут уже оверкил. С другой стороны если нужно, чтобы объект искался по значению в хэш-таблице, то ничего страшного если у него реализовать GetHashCode и т.п., а не заниматься наворачиванием отдельных классов-копораторов. В общем, смотреть надо на конкретные случаи. Идея с запечатанными классами тоже неплоха, хотя и она не решает неоднознчности если скажем Equals реализован по разному у разных, но сравнимых объектов.

Однако согласен, что проблема это системная. В Хаскеле, например, есть классы типов которые элегантно решают данную проблему. Они аналогичны интерфейсам, но реализуются отдельно (не в рамках типа). Это дает возможность реализовывать нужный набор действий по требованию и не захламлять классы. При этом они полиморфны, что предотвращает грабли вроде тех, что создаются операторами сравнения в Шарпе. К тому же методы можно использовать как операторы (в инфиксной записи). Так что операторы реализуются "на раз".
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Багодром: Реализация операторов сравнения
От: _FRED_ Черногория
Дата: 10.04.08 05:35
Оценка:
Здравствуйте, VladD2, Вы писали:

_FR>>Я бы посоветовал вообще никогда не реализовывать Equals\GetHashCode и соответствующих операторов сравнения в типах, если тип не struct или не sealed class : object в понимании C#.


VD>На мой взгляд, советы тут не уместны. Equals\GetHashCode есть и используются довольно часто.


Как показал пример из твоей статьи (и то что доводилось видеть мне ранее), настолько же часто, насколько и бездумно.

VD>Так что если хочется, чтобы объекты вели себя как надо в стандартных коллекциях и т.п., то прийдется их реализовывать.


Вот как раз и нет: для коллекций перегрузка опереторов как раз и не неужна (generic-коллекция не сможет вызвать операторы). Как раз любой стандартной коллекции, которой может потребоваться сравнение элементов (Hashtable, Dictionary<,>, HashSet<,>) можно подсунуть IEqualityComparer\IEqualityComparer<>, который будет дёргаться для проверки на равенство и получения хеша. Реализация логики сравнения в самом классе лишь позволит использовать дефолтный компарер. Это не правильный путь, который ведёт к множеству не нужных (как в приведённом тобой примере) ошибок.

Реализовывать сравнение в классе объекта требуется лишь тогда, когда объект представляет (семантически) простое значение (например, комплексное число, строка, тупла). О том, почему ни в коем случае нельзя реализовывать Equals\GetHashCode в не-immutable типе так же не раз уже говорилось (а DropDownMember как раз не-immutable). И вот именно для таких объектов подходят компараторы.

VD>Что же касается отдельных копораторов, то на мой взгляд во многих случаях случаев и они не нужны. Скажем, для той же сортировки (ради которой и были реализованы все эти методы) лучше использовать функцию получающую лябду-компаратор. Создать ее для конкретного случая не проблема. Это аналогично заданию order by в SQL-запросе.


Проблема будет тогда, когда придётся тоскать её за собой. Конечно, нормальные пацаны уже понаделали себе реализаций IEqualityComparer<>\IComparable, принимающих в конструкторе делегат. Разница между методом и экземпляром тут получается в том, что в классах-коллекциях в конструкторе принято принимать объект-компаратор, а не метод. Если нужна только сортировка — да, согласен, метода в подавляющем большинстве случаев будет достаточно.

VD>А объект-компоратор тут уже оверкил. С другой стороны если нужно, чтобы объект искался по значению в хэш-таблице, то ничего страшного если у него реализовать GetHashCode и т.п., а не заниматься наворачиванием отдельных классов-копораторов.


Как раз и нет: объект-компаратор именно что потребуется для передачи в коллекцию. И в нём как-раз можно будет реализовать логику сравнения, устойчивую к тому, что сравниваются не-immutable объекты. Реализация такой функциональности на уровне класса — говорит попросту о лене разработчика и до хорошего не доводит.

VD>В общем, смотреть надо на конкретные случаи.


Да нет, гораздо понятнее, когда наоборот — правило и критерии едины.

VD>Идея с запечатанными классами тоже неплоха, хотя и она не решает неоднознчности если скажем Equals реализован по разному у разных, но сравнимых объектов.


В этом случае и нужны компараторы, для устранения неоднозначности. В противном случае сам объект под угрозой излишней смысловой перегрузки.

VD>Однако согласен, что проблема это системная. В Хаскеле, например, ...


Угу, везде "хорошо, где нас нет"
... << RSDN@Home 1.2.0 alpha 4 rev. 1048>>
Help will always be given at Hogwarts to those who ask for it.
Re[2]: Багодром: Реализация операторов сравнения
От: _FRED_ Черногория
Дата: 10.04.08 05:39
Оценка: +1
Здравствуйте, _FRED_, Вы писали:

_FR>Я бы посоветовал вообще никогда не реализовывать Equals\GetHashCode и соответствующих операторов сравнения в типах, если тип не struct или не sealed class : object в понимании C#.


Забыл упомянуть и о том, что реализация логики сравнения (Equals\GetHashCode) у не-immutable классов так же порочна. Если значение GetHashCodeзависитот какого-либо из изменяемых полей, то свот какие могут быть пироги: добавляем такой объект в Dictionary<,> в качестве ключа, у него вызывается GetHashCode и запоминается. Потом меняем поле объекта, от которого зависит GetHashCode, а, значит, и Equals. Как вы думаете, еслимы запросим что-либо по этому ключу, то найдём или нет?
... << RSDN@Home 1.2.0 alpha 4 rev. 1048>>
Help will always be given at Hogwarts to those who ask for it.
Re[4]: Багодром: Реализация операторов сравнения
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.04.08 11:13
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Вот как раз и нет: для коллекций перегрузка опереторов как раз и не неужна (generic-коллекция не сможет вызвать операторы).


Какие операторы? Ты же о GetHashcode говоритл...

_FR>Как раз любой стандартной коллекции, которой может потребоваться сравнение элементов (Hashtable, Dictionary<,>, HashSet<,>) можно подсунуть IEqualityComparer\IEqualityComparer<>,


А можно забыть. Да и подсовывание само по себе не очень эстетично. Причем никаких проблем реализовать тот же хэсшь-код нет.

В общем, не стоит упираться рогом по пустякам. Коллекции спроектированы не очень замечательно, но теперь с этим уже ничего не поделать.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Багодром: Реализация операторов сравнения
От: Lloyd Россия  
Дата: 11.04.08 13:13
Оценка: 1 (1)
Здравствуйте, _FRED_, Вы писали:

_FR>Забыл упомянуть и о том, что реализация логики сравнения (Equals\GetHashCode) у не-immutable классов так же порочна. Если значение GetHashCodeзависитот какого-либо из изменяемых полей, то свот какие могут быть пироги: добавляем такой объект в Dictionary<,> в качестве ключа, у него вызывается GetHashCode и запоминается. Потом меняем поле объекта, от которого зависит GetHashCode, а, значит, и Equals. Как вы думаете, еслимы запросим что-либо по этому ключу, то найдём или нет?


В приведенном примере порочно не релализация логики сравнения, а изменение объектов, которые используются как ключи.
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[4]: Багодром: Реализация операторов сравнения
От: _FRED_ Черногория
Дата: 14.04.08 05:57
Оценка:
Здравствуйте, Lloyd, Вы писали:

_FR>>Забыл упомянуть и о том, что реализация логики сравнения (Equals\GetHashCode) у не-immutable классов так же порочна. Если значение GetHashCodeзависитот какого-либо из изменяемых полей, то свот какие могут быть пироги: добавляем такой объект в Dictionary<,> в качестве ключа, у него вызывается GetHashCode и запоминается. Потом меняем поле объекта, от которого зависит GetHashCode, а, значит, и Equals. Как вы думаете, еслимы запросим что-либо по этому ключу, то найдём или нет?


L>В приведенном примере порочно не релализация логики сравнения, а изменение объектов, которые используются как ключи.


Я сторонник того подхода, что код библиотеки должен явно говорить, почему он не работает, или работает не правильно. Библиотека, пользователь которой должен брать на себя ответственность о том, как та работает, теряет преимущество "чёрного ящика" и превоащается в изучении документации\исходников, а не работы, _в простейших ситуациях_. В "простых сценариях" [хорошо спроектированная] библиотека более чем способна 1) не дать пользователю наступить на грабли, и 2) чётко и ясно сообщить о неправильном своём использовании. Поэтому, если какую-то (пускай и дурацкую) ошибку я могу исправить в библиотечном коде, я так и сделаю и не буду вынуждать пользователя думать о том, как можно, а как — нет использовать то, ему предоставляется.

Я считаю порочным то, что библиотека потенциально позволяет наступить на грабли и, думаю, это ошибка библиотеки. Дело это, кажется, вкуса .
... << RSDN@Home 1 alpha 3 rev. 0>>
Help will always be given at Hogwarts to those who ask for it.
Re: return -1; // тоже баг
От: Other Sam Россия  
Дата: 17.04.08 15:23
Оценка:
В методе CompareTo возврат -1 приведет к багу
(обратные операторы будут врать):

DropDownMember d1 = new DropDownMember("A");
// В другом классе реализация IComparable и операторов сравнения такая же как 
// и в классе DropDownMember
KakoyToLeviyClass c1 = new KakoyToLeviyClass();
if (d1 == c1 && c1 == d1) {
} else if (d1 > c1 && c1 < d1) {
} else if (d1 < c1 && c1 > d1) {
} else {
    // Все возможные условия проверены в других if
    // этот else никогда не должен исполняться
    Assert.Fail("Unexpected behavior");
}
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.