Багодром: Реализация операторов сравнения
От: Чистяков Влад (VladD2) Российская Империя www.nemerle.org
Дата: 15.03.08 13:47
Оценка: 1192 (31) +1 -1 :)))
Статья:
Багодром: Реализация операторов сравнения
Автор(ы): Чистяков Влад (VladD2)
Дата: 15.03.2008
Данная статья посвящена вопросу грамотной реализации операторов сравнения. При кажущейся простоте, эта задача несет в себе ряд скрытых трудностей. Реализация операторов сравнения нередко приводит к появлению неприятных ошибок. В основном эта информация касается C#-программистов, но будет полезна тем, кто пишет .NET-код и на других языках.


Авторы:
Чистяков Влад (VladD2)

Аннотация:
Данная статья посвящена вопросу грамотной реализации операторов сравнения. При кажущейся простоте, эта задача несет в себе ряд скрытых трудностей. Реализация операторов сравнения нередко приводит к появлению неприятных ошибок. В основном эта информация касается C#-программистов, но будет полезна тем, кто пишет .NET-код и на других языках.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Багодром: Реализация операторов сравнения
От: Mika Soukhov Stock#
Дата: 03.04.08 19:04
Оценка: 42 (1) +1 :))) :))
Здравствуйте, Kore Sar, Вы писали:

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


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


Только под землю не зарывайтесь.
Re: Багодром: Реализация операторов сравнения
От: _FRED_ Черногория
Дата: 18.04.08 07:18
Оценка: 37 (1) +1 :)
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

ЧВV>Статья:

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


Гхм… (коменты удалил)

Таким образом, общий паттерн реализации операторов будет следующим (паттерн приводится на основе кода класса DropDownMember, приведенного в начале статьи):

public static bool operator ==(DropDownMember m1, DropDownMember m2)
{
  if (object.ReferenceEquals(m1, m2))
    return true;
  
  if (object.ReferenceEquals(m1, null))
    return false;

  return m1.Equals(m2);
}


Гхм… Гхм… Гхм…:

public static bool operator ==(DropDownMember m1, DropDownMember m2)
{
  return Equals(m1, m2);
}




P.S. Для тех, кто не видел:
    public static bool Equals(Object objA, Object objB) 
    {
        if (objA==objB) {
            return true;
        } 
        if (objA==null || objB==null) {
            return false; 
        } 
        return objA.Equals(objB);
    }
... << RSDN@Home 1 alpha 3 rev. 0>>
Help will always be given at Hogwarts to those who ask for it.
Re: Багодром: Реализация операторов сравнения
От: vdimas Россия  
Дата: 27.03.08 15:21
Оценка: 1 (1) +2
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

Кстати, меня весьма раздражает тот факт, что если я переопределил операторы == и !=, то простая проверка:
if(myObj!=null)

приводит к вызову кучи кода, вместо того, чтобы просто заэммитить в байткод проверку на null.
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[9]: Багодром: Реализация операторов сравнения
От: vdimas Россия  
Дата: 31.03.08 22:42
Оценка: +1 -1 :)
Здравствуйте, anton_t, Вы писали:


_>Я вообще статические методы стараюсь писать со спецификацией типа, во избежании недоразумений. Если можно легко избежать лишнего бага, зачем его не избегать?


Не на том уровне "избегание багов" у тебя происходит.
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[4]: Багодром: Реализация операторов сравнения
От: _FRED_ Черногория
Дата: 31.03.08 09:28
Оценка: 6 (1) +1
Здравствуйте, vdimas, Вы писали:

_>>А то ты хочешь странного: я переопределил оператор, но не хочу что бы он переопределялся.

V>Что-то я не понял рассуждения, ты хочешь сказать, что может быть еще какая-то семантика проверки ссылочного типа на null?

Неоднозначность в предлагаемом тобой подходе в том, что вот такой вот код:
MyRefType myObj2 = null;
if(myObj != myObj2) // "Обычное", определённое в типе сравнение

и такой:
if(myObj != null) // Специальное с null

будут работать совсем по-разному.
... << 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[10]: Багодром: Реализация операторов сравнения
От: anton_t Россия  
Дата: 01.04.08 09:38
Оценка: +1 :)
Здравствуйте, _FRED_, Вы писали:

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


_>>Я вообще статические методы стараюсь писать со спецификацией типа, во избежании недоразумений. Если можно легко избежать лишнего бага, зачем его не избегать?


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


Я откуда знаю, я же его избежал. Тебе что не нравится-то?
Re[10]: Багодром: Реализация операторов сравнения
От: _FRED_ Черногория
Дата: 01.04.08 13:52
Оценка: +2
Здравствуйте, VladD2, Вы писали:

VD>Можно было бы принять соглашение, что при сравнении с null производится автоматическое приведение типов к object. Это убрало бы часть граблей и сделало бы поведение интуитивно понятнее.

VD>Видно же, что море людей ходят по этим граблям. Зачем их защищать?

Это бы не уменьшило количество граблей: если сравнение происходит не с литералом "null", а с переменной, имеющей значение null, грабли вылезли бы.

VD>Вообще-то, лучше всего было бы изменить саму схему реализации операторов сравнения. Скажем если реализован метод Equals<X> для некого типа, то автоматически предоставлять возможность сравнения объекта этого типа с X по средством оператора == и !=.


+1 Но не на основании наличия метода, а реализации интерфейса IEquatable<>. Ещё и операторы сравнения генерить автоматом, если реализован IComparable<>…
... << RSDN@Home 1 alpha 3 rev. 0>>
Help will always be given at Hogwarts to those who ask for it.
Re[7]: Багодром: Реализация операторов сравнения
От: Kore Sar  
Дата: 03.04.08 09:26
Оценка: +1 :)
Здравствуйте, s.and, Вы писали:

KS>>Теперь Вы видите, Влад написал что мы защитимся от неверных переданых типов.

KS>>И да, я сомневаюсь, что Влад написал неоптимизированый код.

SA>Едрить твою налево, это можно было и не перепечатывать. Я замысел Влада и так понял. Знаю, что такое оператор as...

SA>В реализации замысла Влада действительно была опечатка, на которую ты сказал (заменить obj на member).

Спасибо, что всё-таки подтвердили мою правоту и признали свою неправоту в том, что это всё-таки опечатка.


SA>Но!

SA>Если obj не DropDownMember и не его наследник, то метод Влада с учетом твоего замечания возвратить -1, что не верно, как неверно и любое другое значение. Метод первым делом должен содержать проверку наподобие этой:

SA>
SA>if (obj == null)
SA>throw ArgumentNullException("obj");
SA>if (object.ReferenceEquals(obj as DropDownMember, null))
SA>throw new ArgumentException("Noncompatible type", "obj");
SA>


SA>Изучайте:

SA>1. правила хорошего тона проверки аргументов;
SA>2. правила реализации методов сравнения.

Влад, Вы поняли? Изучайте!!! Ибо у Вас плохой код!
Re[8]: Багодром: Реализация операторов сравнения
От: Аноним  
Дата: 03.04.08 09:36
Оценка: +1 -1
Здравствуйте, Kore Sar, Вы писали:

KS>Влад, Вы поняли? Изучайте!!! Ибо у Вас плохой код!


Предлагаю не прятаться за авторитет Влада, а признать, что возвращение методом ComnpareTo -1 (да и любого другого значения), если сравниваемый аргумент имеет несовместимый тип — плохой код.
Или же, если имеешь иное мнение, привести свои аргументы.
Re[10]: Багодром: Реализация операторов сравнения
От: s.and  
Дата: 03.04.08 10:01
Оценка: -1 :)
А>>Предлагаю не прятаться за авторитет Влада, а признать, что возвращение методом ComnpareTo -1 (да и любого другого значения), если сравниваемый аргумент имеет несовместимый тип — плохой код.
А>>Или же, если имеешь иное мнение, привести свои аргументы.

KS>Да мне пофигу, хорошо это или плохо. Мне пофигу твоё мнение. Мне пофигу авторитет Влада. Мне пофигу хороший и плохой код в любом понимании этих слов. Мне пофигу вообще эта дискуссия. Я соглашусь со всем чем хочешь, только отстань от меня, ладно?


KS>Я просто жду ответ Влада на свой вопрос.


Э нет... Не отстану. По причинам:
1. нет смысла ждать ответа Влада, т.к. ты заметил действительно опечатку;
2. зачем ты тогда вступил в дискуссию, если, как утверждаешь, хочешь только ответа по поводу опечатки, но не хочешь обсуждать качество предложенных Владом решений.
3. В твоей последней сентенции один из пунктов — наглая ложь. Вот она: "Мне пофигу авторитет Влада". Как только оказалось, что решение Влада, мягко говоря, не идеально, ты тебя тут же кончились аргументы, и ты тут же спрятался за спину своего великого гуру.

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

Тем более, что сам Влад, в отличие от его почитателя, в этом топике совершенно адекватно подискутировал и со скромным автором данного поста.
Re[11]: Багодром: Реализация операторов сравнения
От: Kore Sar  
Дата: 03.04.08 10:11
Оценка: :))
Здравствуйте, s.and, Вы писали:

А>>>Предлагаю не прятаться за авторитет Влада, а признать, что возвращение методом ComnpareTo -1 (да и любого другого значения), если сравниваемый аргумент имеет несовместимый тип — плохой код.

А>>>Или же, если имеешь иное мнение, привести свои аргументы.

KS>>Да мне пофигу, хорошо это или плохо. Мне пофигу твоё мнение. Мне пофигу авторитет Влада. Мне пофигу хороший и плохой код в любом понимании этих слов. Мне пофигу вообще эта дискуссия. Я соглашусь со всем чем хочешь, только отстань от меня, ладно?


KS>>Я просто жду ответ Влада на свой вопрос.


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


Ок, поехали.

SA>1. нет смысла ждать ответа Влада, т.к. ты заметил действительно опечатку;

SA>2. зачем ты тогда вступил в дискуссию, если, как утверждаешь, хочешь только ответа по поводу опечатки, но не хочешь обсуждать качество предложенных Владом решений.
Потому что Вы мне написали "ты не прав". Теперь Вы мне написали что я прав. Я своего от дискуссии добился.
SA>3. В твоей последней сентенции один из пунктов — наглая ложь. Вот она: "Мне пофигу авторитет Влада". Как только оказалось, что решение Влада, мягко говоря, не идеально, ты тебя тут же кончились аргументы, и ты тут же спрятался за спину своего великого гуру.
Хорошо, это наглая ложь.

SA>Интересно, теперь, когда так некрасиво засветился почитатель Влада, сочтет ли Влад целесообразным вступать в эту дискуссию?

О мой кумир, о Влад! Приди! Осени мое чело своим знамением!

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

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

SA>Тем более, что сам Влад, в отличие от его почитателя, в этом топике совершенно адекватно подискутировал и со скромным автором данного поста.

О Влад, осени же ты и меня свои знамением! И видел, у тебя есть меч!



Доволен? А теперь отстань.
Re[12]: Багодром: Реализация операторов сравнения
От: SiAVoL Россия  
Дата: 03.04.08 12:30
Оценка: :))
Здравствуйте, Kore Sar, Вы писали:

KS>о Влад! Приди! Осени мое чело своим знамением!

Надо организовывать секту "Свидетелей Влада". Чую, будет иметь успех...
... << RSDN@Home 1.2.0 alpha rev. 745>>
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[11]: Багодром: Реализация операторов сравнения
От: vdimas Россия  
Дата: 01.04.08 14:51
Оценка: 2 (1)
Здравствуйте, anton_t, Вы писали:

V>>Не на том уровне "избегание багов" у тебя происходит.


_>Это на каком "не на таком"?


Это надо на уровне дизайна класса решать, а не в строках кода.

Объясни, как у тебя вообще может получиться, что в области видимости статического метода без явного указания типа (т.е. в коде определяющего объекта или наследника) может быть случайно вызван не тот метод?

По логике, если ты принял решение о переопределении одноимённого статического метода в классе наследнике (с приставкой new, компилятор тебе напомнит, если забудешь), то ты поступил так именно с целью использовать его _вместо_ аналогичного базового. И грабли тут как раз в явном специфицировании типа, ибо если ты скопируешь/перенесешь код в класс-наследник при рефакторинге, то он будет работать неправильно в контексте наследника, для которого ты _намеренно_ переопределил обсуждаемый статический метод.
... << RSDN@Home 1.2.0 alpha rev. 786>>
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[2]: Багодром: Реализация операторов сравнения
От: anton_t Россия  
Дата: 31.03.08 02:57
Оценка: +1
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, Чистяков Влад (VladD2), Вы писали:


V>Кстати, меня весьма раздражает тот факт, что если я переопределил операторы == и !=, то простая проверка:

V>
V>if(myObj!=null)
V>

V>приводит к вызову кучи кода, вместо того, чтобы просто заэммитить в байткод проверку на null.

Вызывай
!object.ReferenceEquals(myObj, null)

А то ты хочешь странного: я переопределил оператор, но не хочу что бы он переопределялся.
Re[3]: Багодром: Реализация операторов сравнения
От: vdimas Россия  
Дата: 31.03.08 08:55
Оценка: +1
Здравствуйте, anton_t, Вы писали:


_>Вызывай

_>
!object.ReferenceEquals(myObj, null)

_>А то ты хочешь странного: я переопределил оператор, но не хочу что бы он переопределялся.

Что-то я не понял рассуждения, ты хочешь сказать, что может быть еще какая-то семантика проверки ссылочного типа на null?


P.S. в вызове ReferenceEquals специфицировать object не обязательно.
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[5]: Багодром: Реализация операторов сравнения
От: vdimas Россия  
Дата: 31.03.08 11:01
Оценка: +1
Здравствуйте, _FRED_, Вы писали:


_FR>Неоднозначность в предлагаемом тобой подходе в том, что вот такой вот код:

_FR>
_FR>MyRefType myObj2 = null;
_FR>if(myObj != myObj2) // "Обычное", определённое в типе сравнение
_FR>

_FR>и такой:
_FR>
_FR>if(myObj != null) // Специальное с null
_FR>

_FR>будут работать совсем по-разному.

Да, в первом случае будет вызван ReferenceEquals, только я не вижу, чтобы это работало совсем по-разному.
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[7]: Багодром: Реализация операторов сравнения
От: vdimas Россия  
Дата: 31.03.08 12:45
Оценка: +1
Здравствуйте, _FRED_, Вы писали:


_FR>Нет, если в типе MyRefType переопределён оператор == (а разговор-то именно о переопределении операторов), то в первом случае будет вызван он (считаю, что тип myObj так же MyRefType).


Никаких "нет", operator== статический, т.е. тебе всё-равно придётся проверять на null первый аргумент (ссылочного типа, напомню). В общем, разница тут будет только в том случае, если твой operator== содержит баги.
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[4]: Багодром: Реализация операторов сравнения
От: anton_t Россия  
Дата: 31.03.08 16:50
Оценка: :)
Здравствуйте, vdimas, Вы писали:

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



_>>Вызывай

_>>
!object.ReferenceEquals(myObj, null)

_>>А то ты хочешь странного: я переопределил оператор, но не хочу что бы он переопределялся.

V>Что-то я не понял рассуждения, ты хочешь сказать, что может быть еще какая-то семантика проверки ссылочного типа на null?


А почему нет? Зачем создавать искусственные нагромождения правил: если тут null, то будет так-то, а если не null то будет по другому, а по средам ещё как-нибудь.

V>P.S. в вызове ReferenceEquals специфицировать object не обязательно.


Можно, но я предпочитаю писать с object

using System;

namespace ConsoleApplication8
{
    class Program
    {
        public static bool ReferenceEquals(Program p1, Program p2)
        {
            return true;
        }

        static void Main(string[] args)
        {
            Console.WriteLine(ReferenceEquals(new Program(), new Program()));
            Console.WriteLine(object.ReferenceEquals(new Program(), new Program()));
            Console.ReadLine();
        }
    }
}
Re[8]: Багодром: Реализация операторов сравнения
От: anton_t Россия  
Дата: 31.03.08 18:39
Оценка: -1
Здравствуйте, _FRED_, Вы писали:

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


V>>>>>P.S. в вызове ReferenceEquals специфицировать object не обязательно.

_>>>>Можно, но я предпочитаю писать с object

_FR>>>Хоть раз в жизни пригодилось? Чем занимался собственный ReferenceEquals?


_>>Что пригодилось? ReferenceEquals ни разу не переопределял и вам не советую.


_FR>"писать с object"? Ты сам заявил, почему предпочитаешь "писать с object". Так вот хоть раз в жизни пригодился тот случай, что ты сам в примере привёл?


Я вообще статические методы стараюсь писать со спецификацией типа, во избежании недоразумений. Если можно легко избежать лишнего бага, зачем его не избегать?
Re[3]: Багодром: Реализация операторов сравнения
От: s.and  
Дата: 02.04.08 12:00
Оценка: :)
SA>>Уж лучше бы вообще отказались от перегрузки операторов и пользовались методами CLS-совместимыми аналогами перегаруженных операторов (ну, там static Equals, Add, Divide и и т.д.).

VD>Это тоже не очень хороший выход. Все же читабельность понижается. Лучшим выходом было бы изменить принципы определения операторов и ввести в язык средства предотвращения наступания на грабли (особенно на распространенные).

Согласен.
VD> Вот тот же запрет на сравнение с null типов определяющих операторы сравнения дал бы очень многое.
Да, это было бы элегантным решением. Причем, в существующем C#-стиле, когда компилятор запрещает какую-либо граблеопасную конструкцию для компиляции с выдачей соответствующих предупреждения и рекомендации.
Например:
сравнение myObj == null (с нетипизированным null) недопустимо, т.к класс MyObj реализует оператор ==. Выполните приведение к object ((object)myObj == null) или вызовите ReferenceEquals
Re: Багодром: Реализация операторов сравнения
От: Kore Sar  
Дата: 02.04.08 14:16
Оценка: +1
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

ЧВV>Статья:

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


ЧВV>Авторы:

ЧВV> Чистяков Влад (VladD2)


Влад, не знаю говорили Вам уже или нет (облом всю ветку читать).

Сегодня получили новый журнал #4'2007. Вижу там эту Вашу статью. На стр. 51 есть "общий паттерн реализации операторов сравнения". Присмотритесь к фукнции CompareTo.


public int CompareTo(object obj, StringComparison stringComparison)
{
  var member = obj as DropDownMember;
  // тут коментарии с объяснением, что мы типа убивам двух зайцев сразу ...
  if (!object.ReferenceEquals(obj, null))
    return string.Compare(this.Label, member.Label, stringComparison);
  
  return -1;
}


Вероятно вместо выделеного obj должен был стоять member.
Я прав?
Re[10]: Багодром: Реализация операторов сравнения
От: Lloyd Россия  
Дата: 03.04.08 09:42
Оценка: :)
Здравствуйте, Kore Sar, Вы писали:

KS>Я просто жду ответ Влада на свой вопрос.


Тут явно не хватает "глубокоуважаемого".
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[12]: Багодром: Реализация операторов сравнения
От: s.and  
Дата: 03.04.08 10:18
Оценка: -1
KS>Ок, поехали.

SA>>1. нет смысла ждать ответа Влада, т.к. ты заметил действительно опечатку;

SA>>2. зачем ты тогда вступил в дискуссию, если, как утверждаешь, хочешь только ответа по поводу опечатки, но не хочешь обсуждать качество предложенных Владом решений.
KS>Потому что Вы мне написали "ты не прав". Теперь Вы мне написали что я прав. Я своего от дискуссии добился.
Я написал, что ты прав только в контексте (неверного) примера Влада. А первоначально ты писал, что в ReferenceEquals важно приведение, без контекста. В итоге пришли к консенсусу, но только по этому вопросу.

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

SA>>3. В твоей последней сентенции один из пунктов — наглая ложь. Вот она: "Мне пофигу авторитет Влада". Как только оказалось, что решение Влада, мягко говоря, не идеально, ты тебя тут же кончились аргументы, и ты тут же спрятался за спину своего великого гуру.

KS>Хорошо, это наглая ложь.
Пишешь правду, но неискренне.

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

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[2]: Багодром: Реализация операторов сравнения
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.04.08 10:51
Оценка: +1
Здравствуйте, alexanderfedin, Вы писали:

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


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

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

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


Понятно, хотя и печально. Но это проблема не программистов, а компаний. Точнее их руководства. Мне кажется, что есть ряд задач которые лучше решаются компактной группой высокопроффесиональных спецов, а не гурьбой малоквалифицированных кадров лихо закидывающих буденовками неприятеля. На мой взгляд разработка компиляторов и интеграции языков с IDE как раз такой случай. Уверен, что в МС работает масса отличных спецов которые и двигают компанию вперед. Более того данная статья ни в коем разе не наезд на МС. Это просто иллюстрация которая не только попалась под руку, но и изрядно потрепала нервы. Наверно, надо было вместо конкретных исходников и компании сказать что-то размытое и обтекаемое, но мне показалось, что реальный пример из реальной жизни будет убедительнее. Ведь цель предотвратить подобные вещи в будущем. Точнее уменьшить их число.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
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: Багодром: Реализация операторов сравнения
От: Хнык Россия  
Дата: 28.04.08 18:53
Оценка: :)
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

ЧВV>Статья:

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


ЧВV>Авторы:

ЧВV> Чистяков Влад (VladD2)

ЧВV>Аннотация:

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


  // В этом месте, если m1 равна null, то m1 уже не может быть 
  // равна null. Стало быть, объекты не равны, и можно вернуть false.
  if (object.ReferenceEquals(m1, null))
    return false;


Опечатка. Имхо, менее претенциозное название статье не повредило бы. Или проверить пицот раз.
Мну думает. Значит. Ага.
Re: Багодром: Реализация операторов сравнения
От: Othello  
Дата: 19.03.08 08:06
Оценка:
А почему нету в новостях. Или хотябы в статьях.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Багодром: Реализация операторов сравнения
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 19.03.08 08:17
Оценка:
Здравствуйте, Othello, Вы писали:

O>А почему нету в новостях. Или хотябы в статьях.


потому что это не статья, а анонс
... << RSDN@Home 1.2.0 alpha 3 rev. 948>>
Re[3]: Багодром: Реализация операторов сравнения
От: Othello  
Дата: 19.03.08 08:32
Оценка:
OE>потому что это не статья, а анонс

Статья:
Багодром: Реализация операторов сравнения

написано же — статья

а раздела — анонсы нету — где их все посмотреть ?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: Багодром: Реализация операторов сравнения
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 19.03.08 10:32
Оценка:
Здравствуйте, Othello, Вы писали:

O>а раздела — анонсы нету — где их все посмотреть ?


как и написано в новостях — http://rsdn.ru/summary/4688.xml
... << RSDN@Home 1.2.0 alpha 3 rev. 948>>
Re: Багодром: Реализация операторов сравнения
От: anton_t Россия  
Дата: 27.03.08 17:59
Оценка:
Здравствуйте, Чистяков Влад (VladD2), Вы писали:

ЧВV>Статья:

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


ЧВV>Авторы:

ЧВV> Чистяков Влад (VladD2)

ЧВV>Аннотация:

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

Можно ли каким-нибудь образом заказать журнал по интернету? http://rsdn.ru/RsdnMag/Subscribe/OrderPost.aspx который месяц (если не который год) не работает.
Re[6]: Багодром: Реализация операторов сравнения
От: _FRED_ Черногория
Дата: 31.03.08 11:11
Оценка:
Здравствуйте, vdimas, Вы писали:

_FR>>Неоднозначность в предлагаемом тобой подходе в том, что вот такой вот код:

_FR>>MyRefType myObj2 = null;
_FR>>if(myObj != myObj2) // "Обычное", определённое в типе сравнение


V>Да, в первом случае будет вызван ReferenceEquals, только я не вижу, чтобы это работало совсем по-разному.


Нет, если в типе MyRefType переопределён оператор == (а разговор-то именно о переопределении операторов), то в первом случае будет вызван он (считаю, что тип myObj так же MyRefType).
... << RSDN@Home 1.2.0 alpha 4 rev. 1048>>
Help will always be given at Hogwarts to those who ask for it.
Re[8]: Багодром: Реализация операторов сравнения
От: _FRED_ Черногория
Дата: 31.03.08 14:28
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Никаких "нет", operator== статический, т.е. тебе всё-равно придётся проверять на null первый аргумент (ссылочного типа, напомню). В общем, разница тут будет только в том случае, если твой operator== содержит баги.


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

V>>P.S. в вызове ReferenceEquals специфицировать object не обязательно.

_>Можно, но я предпочитаю писать с object

Хоть раз в жизни пригодилось? Чем занимался собственный ReferenceEquals?
... << RSDN@Home 1.2.0 alpha 4 rev. 1048>>
Help will always be given at Hogwarts to those who ask for it.
Re[6]: Багодром: Реализация операторов сравнения
От: anton_t Россия  
Дата: 31.03.08 18:24
Оценка:
Здравствуйте, _FRED_, Вы писали:

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


V>>>P.S. в вызове ReferenceEquals специфицировать object не обязательно.

_>>Можно, но я предпочитаю писать с object

_FR>Хоть раз в жизни пригодилось? Чем занимался собственный ReferenceEquals?


Что пригодилось? ReferenceEquals ни разу не переопределял и вам не советую.
Re[7]: Багодром: Реализация операторов сравнения
От: _FRED_ Черногория
Дата: 31.03.08 18:33
Оценка:
Здравствуйте, anton_t, Вы писали:

V>>>>P.S. в вызове ReferenceEquals специфицировать object не обязательно.

_>>>Можно, но я предпочитаю писать с object

_FR>>Хоть раз в жизни пригодилось? Чем занимался собственный ReferenceEquals?


_>Что пригодилось? ReferenceEquals ни разу не переопределял и вам не советую.


"писать с object"? Ты сам заявил, почему предпочитаешь "писать с object". Так вот хоть раз в жизни пригодился тот случай, что ты сам в примере привёл?
... << RSDN@Home 1.2.0 alpha 4 rev. 1048>>
Help will always be given at Hogwarts to those who ask for it.
Re[9]: Багодром: Реализация операторов сравнения
От: vdimas Россия  
Дата: 31.03.08 22:39
Оценка:
Здравствуйте, _FRED_, Вы писали:

V>>Никаких "нет", operator== статический, т.е. тебе всё-равно придётся проверять на null первый аргумент (ссылочного типа, напомню). В общем, разница тут будет только в том случае, если твой operator== содержит баги.


_FR>Разница в том, что при одних аргументах (переменные) будет выполняться один код, а при других (null) — другой.


Т.е. можно считать, что аргументы исчерпаны?
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[10]: Багодром: Реализация операторов сравнения
От: anton_t Россия  
Дата: 01.04.08 02:52
Оценка:
Здравствуйте, vdimas, Вы писали:

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



_>>Я вообще статические методы стараюсь писать со спецификацией типа, во избежании недоразумений. Если можно легко избежать лишнего бага, зачем его не избегать?


V>Не на том уровне "избегание багов" у тебя происходит.


Это на каком "не на таком"?
Re[10]: Багодром: Реализация операторов сравнения
От: _FRED_ Черногория
Дата: 01.04.08 03:29
Оценка:
Здравствуйте, vdimas, Вы писали:

_FR>>Разница в том, что при одних аргументах (переменные) будет выполняться один код, а при других (null) — другой.

V>Т.е. можно считать, что аргументы исчерпаны?

Аргументы к чему? Мы же ни о чём реальном не говорим. У меня нет оснований считать, что когда либо будет сделано так, как ты тут предлагаешь, так что и аргументировать нечего Это тебе, если хочется убедиться в своей правоте, следует завести тикет на connect-те и привести свои аргументы менеджерам из МС
... << RSDN@Home 1.2.0 alpha 4 rev. 1048>>
Help will always be given at Hogwarts to those who ask for it.
Re[9]: Багодром: Реализация операторов сравнения
От: _FRED_ Черногория
Дата: 01.04.08 03:32
Оценка:
Здравствуйте, anton_t, Вы писали:

_>Я вообще статические методы стараюсь писать со спецификацией типа, во избежании недоразумений. Если можно легко избежать лишнего бага, зачем его не избегать?


Так вот я тебя о том и спрашиваю, хоть раз тебе удалось избежать подобного бага со статическими методами, объявленными в Object? А с методами в других классах фреймворка? А с методами собственных классов?
... << RSDN@Home 1.2.0 alpha 4 rev. 1048>>
Help will always be given at Hogwarts to those who ask for it.
Re: Багодром: Реализация операторов сравнения
От: s.and  
Дата: 01.04.08 06:43
Оценка:
Статья хорошая.

Но вот вопрос к желающим, чтобы при проверке
myObj == null
вызывалась именно проверка на
null
(т.е., фактически
(object)myObj == null
или
object.RererenceEquals(myObj, null)
):

А что, произойдет в случае вызова
myObj1 == myObj2
, если оба равны
null
. Понятно, что перегруженный оператор сравнения (ессно, рассматриваем случай именно с перегруженным оператором). А вот что произойдет: возвращаемое значение может оказаться отличным от проверки
myObj1 == null
. А это было бы совсем неправильно.

Так что надо просто корректно реализовывать оператор сравнения, чтобы там в первой же строке проверялось равенство на null (чтобы не вызывался лишний код). Но кто за этим будет следить, если даже в Микрософт плохо реализуют эти операторы.
Уж лучше бы вообще отказались от перегрузки операторов и пользовались методами CLS-совместимыми аналогами перегаруженных операторов (ну, там static Equals, Add, Divide и и т.д.).
Re[2]: Багодром: Реализация операторов сравнения
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.04.08 12:21
Оценка:
Здравствуйте, anton_t, Вы писали:

_>Можно ли каким-нибудь образом заказать журнал по интернету? http://rsdn.ru/RsdnMag/Subscribe/OrderPost.aspx который месяц (если не который год) не работает.


В www.bolero.ru
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Багодром: Реализация операторов сравнения
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.04.08 12:26
Оценка:
Здравствуйте, _FRED_, Вы писали:

V>>Никаких "нет", operator== статический, т.е. тебе всё-равно придётся проверять на null первый аргумент (ссылочного типа, напомню). В общем, разница тут будет только в том случае, если твой operator== содержит баги.


_FR>Разница в том, что при одних аргументах (переменные) будет выполняться один код, а при других (null) — другой.


Можно было бы принять соглашение, что при сравнении с null производится автоматическое приведение типов к object. Это убрало бы часть граблей и сделало бы поведение интуитивно понятнее.

Видно же, что море людей ходят по этим граблям. Зачем их защищать?

ЗЫ

Вообще-то, лучше всего было бы изменить саму схему реализации операторов сравнения. Скажем если реализован метод Equals<X> для некого типа, то автоматически предоставлять возможность сравнения объекта этого типа с X по средством оператора == и !=.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Багодром: Реализация операторов сравнения
От: vdimas Россия  
Дата: 01.04.08 14:51
Оценка:
Здравствуйте, _FRED_, Вы писали:


_FR>Аргументы к чему? Мы же ни о чём реальном не говорим. У меня нет оснований считать, что когда либо будет сделано так, как ты тут предлагаешь, так что и аргументировать нечего Это тебе, если хочется убедиться в своей правоте, следует завести тикет на connect-те и привести свои аргументы менеджерам из МС


Жаль, что вышла такая бесполезная дисскуссия. Вопрос был: "почему бы не заменить одну конструкцию на другую, семантически эквивалентную"? Твой ответ был потрясающий: "потому что это будет другая конструкция". На самом деле мне были интересны размышления и обмен мнениями о возможных граблях — может я что-нибудь упустил. Как правильно заметил Влад, null — это нетипизированное значение, и при сравнении с ним ссылочного типа можно приводить к object.
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[11]: Багодром: Реализация операторов сравнения
От: vdimas Россия  
Дата: 02.04.08 07:36
Оценка:
Здравствуйте, _FRED_, Вы писали:


_FR>+1 Но не на основании наличия метода, а реализации интерфейса IEquatable<>. Ещё и операторы сравнения генерить автоматом, если реализован IComparable<>…


Resharper как раз любезно подсвечивает эту ситуацию и предлагает сам реализовать == и !=, а для IComparable еще и GetHashCode().
Re[2]: Багодром: Реализация операторов сравнения
От: VladD2 Российская Империя www.nemerle.org
Дата: 02.04.08 10:42
Оценка:
Здравствуйте, s.and, Вы писали:


SA>Так что надо просто корректно реализовывать оператор сравнения, чтобы там в первой же строке проверялось равенство на null (чтобы не вызывался лишний код).


Несомненно! В текущей ситуации на C# по другому и быть не может. Просто есть шанс, что статью читают будущие разработчики нового мега-языка который после нашей смерти (например ) завоюет всемирную любовь. Так вот если он сделает выводы и умудрится не заложить подобные грабли в этот новый язык, то лично я буду счастлив.

SA> Но кто за этим будет следить, если даже в Микрософт плохо реализуют эти операторы.


Дык, на то и нужно живое описание проблемы. Ведь оповещен значит вооружен!

SA>Уж лучше бы вообще отказались от перегрузки операторов и пользовались методами CLS-совместимыми аналогами перегаруженных операторов (ну, там static Equals, Add, Divide и и т.д.).


Это тоже не очень хороший выход. Все же читабельность понижается. Лучшим выходом было бы изменить принципы определения операторов и ввести в язык средства предотвращения наступания на грабли (особенно на распространенные). Вот тот же запрет на сравнение с null типов определяющих операторы сравнения дал бы очень многое.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Багодром: Реализация операторов сравнения
От: s.and  
Дата: 03.04.08 08:04
Оценка:
KS>Влад, не знаю говорили Вам уже или нет (облом всю ветку читать).

KS>Сегодня получили новый журнал #4'2007. Вижу там эту Вашу статью. На стр. 51 есть "общий паттерн реализации операторов сравнения". Присмотритесь к фукнции CompareTo.



KS>
KS>public int CompareTo(object obj, StringComparison stringComparison)
KS>{
KS>  var member = obj as DropDownMember;
KS>  // тут коментарии с объяснением, что мы типа убивам двух зайцев сразу ...
KS>  if (!object.ReferenceEquals(obj, null))
KS>    return string.Compare(this.Label, member.Label, stringComparison);
  
KS>  return -1;
KS>}
KS>


KS>Вероятно вместо выделеного obj должен был стоять member.

KS>Я прав?

Не прав.
Приведение obj в member не требуется. ReferenceEquals — это ссылочное сравнение.
Однако, более правильным был бы вот такой код:
public int CompareTo(object obj, StringComparison stringComparison)
{
  // тут коментарии с объяснением, что мы типа убивам двух зайцев сразу ...
  if (!object.ReferenceEquals(obj, null))
  {
    var member = obj as DropDownMember;
    return string.Compare(this.Label, member.Label, stringComparison);
  }
  
  return -1;
}
Re[3]: Багодром: Реализация операторов сравнения
От: Kore Sar  
Дата: 03.04.08 08:11
Оценка:
KS>>Вероятно вместо выделеного obj должен был стоять member.
KS>>Я прав?

SA>Не прав.

SA>Приведение obj в member не требуется. ReferenceEquals — это ссылочное сравнение.

Не требуется, говоришь. Ну-ну.


SA>Однако, более правильным был бы вот такой код:

SA>
SA>public int CompareTo(object obj, StringComparison stringComparison)
SA>{
SA>  // тут коментарии с объяснением, что мы типа убивам двух зайцев сразу ...
SA>  if (!object.ReferenceEquals(obj, null))
SA>  {
SA>    var member = obj as DropDownMember;
SA>    return string.Compare(this.Label, member.Label, stringComparison);
SA>  }
  
SA>  return -1;
SA>}
SA>


)))))))))

А помоему я всё-таки прав.

Вот скажите, к чему приведёт этот ваш код, если CompareTo будет вызвано вот так?
myClass.CompareTo(new string("abc"), StringComparison.CurrentCulture);
Re[4]: Багодром: Реализация операторов сравнения
От: s.and  
Дата: 03.04.08 08:39
Оценка:
Re[4]: Багодром: Реализация операторов сравнения в избранное msdn новое ответить всё подписка модер.
От: s.and
Дата: 03.04.08 13:37
Здравствуйте, Kore Sar, Вы писали:

KS>>>Вероятно вместо выделеного obj должен был стоять member.

KS>>>Я прав?

SA>>Не прав.

SA>>Приведение obj в member не требуется. ReferenceEquals — это ссылочное сравнение.

KS>Не требуется, говоришь. Ну-ну.


Чувак, еще раз. ReferenceEquals — это ссылочное сравнение. Приведение obj к иному типу не нужно. Хотя и повредит лишь в плане накладных расходов на приведение типа.

SA>>Однако, более правильным был бы вот такой код:

SA>>

SA>>public int CompareTo(object obj, StringComparison stringComparison)

SA>>{
SA>> // тут коментарии с объяснением, что мы типа убивам двух зайцев сразу ...
SA>> if (!object.ReferenceEquals(obj, null))
SA>> {
SA>> var member = obj as DropDownMember;
SA>> return string.Compare(this.Label, member.Label, stringComparison);
SA>> }

SA>> return -1;

SA>>}
SA>>



KS>)))))))))


KS>А помоему я всё-таки прав.


KS>Вот скажите, к чему приведёт этот ваш код, если CompareTo будет вызвано вот так?

KS>

KS>myClass.CompareTo(new string("abc"), StringComparison.CurrentCulture);

KS>



Приведет к ошибке в момент приведение типа. Точно так же, как в коде Влада.
У меня не было цели исправить код Влада. Я лишь оптимизирован его.

А вот ты хотел предложить именно исправить код. И предложил неверное решение. Если в указанном тобой месте заменить obj на member, то получим:

public int CompareTo(object obj, StringComparison stringComparison)
{
var member = obj as DropDownMember;
// тут коментарии с объяснением, что мы типа убивам двух зайцев сразу ...
if (!object.ReferenceEquals(member, null))
return string.Compare(this.Label, member.Label, stringComparison);

return -1;
}

И что же все таки получим? Если obj — не DropDownMember, то метод возвратит -1. Что за глупость? Метод должен сгенерировать исключение с сообщением а-ля "неверный тип"!

HotLog
Re[5]: Багодром: Реализация операторов сравнения
От: Kore Sar  
Дата: 03.04.08 08:51
Оценка:
Здравствуйте, s.and, Вы писали:

KS>>Не требуется, говоришь. Ну-ну.


SA>Чувак, еще раз. ReferenceEquals — это ссылочное сравнение. Приведение obj к иному типу не нужно. Хотя и повредит лишь в плане накладных расходов на приведение типа.


Я это знаю.


SA>А вот ты хотел предложить именно исправить код. И предложил неверное решение. Если в указанном тобой месте заменить obj на member, то получим:


SA>public int CompareTo(object obj, StringComparison stringComparison)

SA>{
SA> var member = obj as DropDownMember;
SA> // тут коментарии с объяснением, что мы типа убивам двух зайцев сразу ...
SA> if (!object.ReferenceEquals(member, null))
SA> return string.Compare(this.Label, member.Label, stringComparison);

SA> return -1;

SA>}

SA>И что же все таки получим? Если obj — не DropDownMember, то метод возвратит -1. Что за глупость? Метод должен сгенерировать исключение с сообщением а-ля "неверный тип"!



Ага. Я понял Вашу мысль.
Вы, видать, не видели статью. У Вас же нет журнала под рукой, я угадал?

Я там написал
// тут коментарии с объяснением, что мы типа убивам двух зайцев сразу ...


А теперь давайте я Вам перепечатаю, что же в этих коментариях Влад на самом деле написал.
// Переменная member будет равна null в двух случаях:
// 1) если null-у была равна переменная obj;
// 2) если obj имеет тип, несовместимый (не являещийся наследником) с DropDownMember (этот класс).
// Таким образом, мы защищаемся и от того, что нам может быть передано значение null,
// и от того, что нам может быть передана ссылка на объект неверного типа.


Теперь Вы видите, Влад написал что мы защитимся от неверных переданых типов.
И да, я сомневаюсь, что Влад написал неоптимизированый код.
Re[6]: Багодром: Реализация операторов сравнения
От: s.and  
Дата: 03.04.08 09:12
Оценка:
Re[6]: Багодром: Реализация операторов сравнения в избранное msdn новое ответить всё подписка модер.
От: s.and
Дата: 03.04.08 14:10
KS>Ага. Я понял Вашу мысль.
KS>Вы, видать, не видели статью. У Вас же нет журнала под рукой, я угадал?
Статью видел в только в сокращенном электронном виде. В печатном, с обсуждаемым примером нет. Но давай вернемся к этому примеру:

KS>А теперь давайте я Вам перепечатаю, что же в этих коментариях Влад на самом деле написал.

KS>

KS>// Переменная member будет равна null в двух случаях:

KS>// 1) если null-у была равна переменная obj;
KS>// 2) если obj имеет тип, несовместимый (не являещийся наследником) с DropDownMember (этот класс).
KS>// Таким образом, мы защищаемся и от того, что нам может быть передано значение null,
KS>// и от того, что нам может быть передана ссылка на объект неверного типа.
KS>



KS>Теперь Вы видите, Влад написал что мы защитимся от неверных переданых типов.

KS>И да, я сомневаюсь, что Влад написал неоптимизированый код.

Едрить твою налево, это можно было и не перепечатывать. Я замысел Влада и так понял. Знаю, что такое оператор as...
В реализации замысла Влада действительно была опечатка, на которую ты сказал (заменить obj на member).
Но!
Если obj не DropDownMember и не его наследник, то метод Влада с учетом твоего замечания возвратить -1, что не верно, как неверно и любое другое значение. Метод первым делом должен содержать проверку наподобие этой:

if (obj == null)
throw ArgumentNullException("obj");
if (object.ReferenceEquals(obj as DropDownMember, null))
throw new ArgumentException("Noncompatible type", "obj");



Изучайте:
1. правила хорошего тона проверки аргументов;
2. правила реализации методов сравнения.
Re[9]: Багодром: Реализация операторов сравнения
От: Kore Sar  
Дата: 03.04.08 09:40
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Kore Sar, Вы писали:


KS>>Влад, Вы поняли? Изучайте!!! Ибо у Вас плохой код!


А>Предлагаю не прятаться за авторитет Влада, а признать, что возвращение методом ComnpareTo -1 (да и любого другого значения), если сравниваемый аргумент имеет несовместимый тип — плохой код.

А>Или же, если имеешь иное мнение, привести свои аргументы.

Да мне пофигу, хорошо это или плохо. Мне пофигу твоё мнение. Мне пофигу авторитет Влада. Мне пофигу хороший и плохой код в любом понимании этих слов. Мне пофигу вообще эта дискуссия. Я соглашусь со всем чем хочешь, только отстань от меня, ладно?

Я просто жду ответ Влада на свой вопрос.
Re[13]: Багодром: Реализация операторов сравнения
От: Kore Sar  
Дата: 03.04.08 10:21
Оценка:
s.and, Вы самый педантичный в мире человек, что я когда-либо встречал.
Re[14]: Багодром: Реализация операторов сравнения
От: Аноним  
Дата: 03.04.08 10:27
Оценка:
Здравствуйте, Kore Sar, Вы писали:

KS>s.and, Вы самый педантичный в мире человек, что я когда-либо встречал.

Возможно.
Но мы обсуждали операторы сравнения, а в этой области не обойтись без пристального внимания к деталям. Иначе получается то, что Влад как раз и критиковал в своей неплохой статье.
Re[4]: Багодром: Реализация операторов сравнения
От: eugen1001  
Дата: 03.04.08 12:22
Оценка:
Здравствуйте, s.and, Вы писали:

SA>Например:

SA>сравнение myObj == null (с нетипизированным null) недопустимо, т.к класс MyObj реализует оператор ==. Выполните приведение к object ((object)myObj == null) или вызовите ReferenceEquals

А не проще сразу IsNull(object)?
... << RSDN@Home 1.2.0 alpha rev. 775>>
Re[5]: Багодром: Реализация операторов сравнения
От: s.and  
Дата: 03.04.08 12:50
Оценка:
SA>>Например:
SA>>сравнение myObj == null (с нетипизированным null) недопустимо, т.к класс MyObj реализует оператор ==. Выполните приведение к object ((object)myObj == null) или вызовите ReferenceEquals

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


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

А если бы был, то это было бы сродни использованию CLS-совместимых static Equals, Add, Divide (вместо ==, +, / ) и т.д. вместо операторов. Т.е., совсем без операторов. Но вроде как такой код не совсем нагляден. С другой строны, если столько граблей из за этих операторов....
Re[4]: Багодром: Реализация операторов сравнения
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.04.08 12:57
Оценка:
Здравствуйте, s.and, Вы писали:

VD>> Вот тот же запрет на сравнение с null типов определяющих операторы сравнения дал бы очень многое.

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

Собственно, именно так и сделано в компиляторе Nemerle, о чем и было сказано в статье.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Багодром: Реализация операторов сравнения
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.04.08 13:03
Оценка:
Здравствуйте, Kore Sar, Вы писали:

KS>Вероятно вместо выделеного obj должен был стоять member.

KS>Я прав?

Да — это очепятка.

Если кто непонял почему надо использовать именно member, поясню...

Дело в том, что в CompareTo может быть передана ссылка на объект не того типа. Тогда оператор as (о граблях которого была отдельная статья) возвратит null и проверка на ссылку не пройдет. Это убережет от доступа по null-указателю и за одно приведет к верному результату — CompareTo возвратит -1.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Багодром: Реализация операторов сравнения
От: Kore Sar  
Дата: 03.04.08 13:06
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Kore Sar, Вы писали:


KS>>Вероятно вместо выделеного obj должен был стоять member.

KS>>Я прав?

VD>Да — это очепятка.


VD>Если кто непонял почему надо использовать именно member, поясню...


VD>Дело в том, что в CompareTo может быть передана ссылка на объект не того типа. Тогда оператор as (о граблях которого была отдельная статья) возвратит null и проверка на ссылку не пройдет. Это убережет от доступа по null-указателю и за одно приведет к верному результату — CompareTo возвратит -1.


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

Влад, мы тут организовываем секту "Свидетей Влада". Вы не против?
Re[5]: Багодром: Реализация операторов сравнения
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.04.08 13:07
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>>> Вот тот же запрет на сравнение с null типов определяющих операторы сравнения дал бы очень многое.

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

VD>Собственно, именно так и сделано в компиляторе Nemerle, о чем и было сказано в статье.


Кстати, если бы компилятор C#-а предупреждал бы о том, что переменная не используется, ошибки можно было бы избежать. Тот же Немерловый компилятор такие предупреждения делает. Наскольк мне известно их делает и РеШарпер, но я им не пользуюсь.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Багодром: Реализация операторов сравнения
От: s.and  
Дата: 03.04.08 13:11
Оценка:
VD>Дело в том, что в CompareTo может быть передана ссылка на объект не того типа. Тогда оператор as (о граблях которого была отдельная статья) возвратит null и проверка на ссылку не пройдет. Это убережет от доступа по null-указателю и за одно приведет к верному результату — CompareTo возвратит -1.

А можно ссылку на статью об "as"?
Re[4]: Багодром: Реализация операторов сравнения
От: Lloyd Россия  
Дата: 03.04.08 13:12
Оценка:
Здравствуйте, Kore Sar, Вы писали:

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


Это ты про себя "мы"?
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[7]: Багодром: Реализация операторов сравнения
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.04.08 13:13
Оценка:
Здравствуйте, s.and, Вы писали:

SA>Если obj не DropDownMember и не его наследник, то метод Влада с учетом твоего замечания возвратить -1, что не верно, как неверно и любое другое значение. Метод первым делом должен содержать проверку наподобие этой:


SA>
SA>if (obj == null)
SA>throw ArgumentNullException("obj");
SA>if (object.ReferenceEquals(obj as DropDownMember, null))
SA>throw new ArgumentException("Noncompatible type", "obj");
SA>


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

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

ЗЫ

В общем, я смотрю на нас на все тут весна действует и всем поспорить охота.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Багодром: Реализация операторов сравнения
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.04.08 13:15
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>Тут явно не хватает "глубокоуважаемого".


Я тут.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
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[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: Багодром: Реализация операторов сравнения
От: _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[4]: Багодром: Реализация операторов сравнения
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.04.08 11:13
Оценка:
Здравствуйте, _FRED_, Вы писали:

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


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

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


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

В общем, не стоит упираться рогом по пустякам. Коллекции спроектированы не очень замечательно, но теперь с этим уже ничего не поделать.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
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");
}
Re: Багодром: Реализация операторов сравнения
От: dimaka Россия http://dmitry-pavlov.com
Дата: 23.04.08 11:38
Оценка:
Здравствуйте, Чистяков Влад (VladD2):

Относительно реализации операторов — хорошая статья. Спасибо.

Относительно MPF и Navigation Bar-a, следовало бы на Microsoft Connect bug запостить. Глядишь в следующей версии VS SDK уже и поправили б Всем бы польза была.

А так — чего хулить-то без толку?
Remote ASP.NET / C# Developer
Re[2]: Багодром: Реализация операторов сравнения
От: Andrbig  
Дата: 24.04.08 09:42
Оценка:
Здравствуйте, dimaka, Вы писали:


D>Относительно MPF и Navigation Bar-a, следовало бы на Microsoft Connect bug запостить. Глядишь в следующей версии VS SDK уже и поправили б Всем бы польза была.


D>А так — чего хулить-то без толку?


А есть уверенность, что этого постинга станет лучше? Один раз баг запостили, так эти деятели сделали только хуже...
Re[2]: Багодром: Реализация операторов сравнения
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.10.08 14:53
Оценка:
Здравствуйте, dimaka, Вы писали:

D>Относительно MPF и Navigation Bar-a, следовало бы на Microsoft Connect bug запостить. Глядишь в следующей версии VS SDK уже и поправили б Всем бы польза была.


D>А так — чего хулить-то без толку?


Дык. Толк как не странно есть. Данный проект выложели на www.codeplex.com/mpfproj
Так что теперь (наверно) можно даже самим баги будет править.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Багодром: Реализация операторов сравнения
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 04.10.08 21:42
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Дык. Толк как не странно есть. Данный проект выложели на www.codeplex.com/mpfproj


Это не весь MPF, а крохотный его кусочек, ответсвенный за создание собственных типов проектов.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111 on Windows Vista 6.0.6001.65536>>
AVK Blog
Re[4]: Багодром: Реализация операторов сравнения
От: Блудов Павел Россия  
Дата: 06.10.08 05:10
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Это не весь MPF, а крохотный его кусочек, ответсвенный за создание собственных типов проектов.

Тем не менее, этого кусочка достаточно чтобы собрать интеграцию студии с Немерлем.
Если бы ещё regpkg.exe куда выложили, так и vssdk вообще не нужно было бы ставить.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.