Re[9]: Багодром: Реализация операторов сравнения
От: vdimas Россия  
Дата: 31.03.08 22:42
Оценка: +1 -1 :)
Здравствуйте, anton_t, Вы писали:


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


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

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


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


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


Я откуда знаю, я же его избежал. Тебе что не нравится-то?
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[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[11]: Багодром: Реализация операторов сравнения
От: vdimas Россия  
Дата: 01.04.08 14:51
Оценка:
Здравствуйте, _FRED_, Вы писали:


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


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

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


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


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

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

По логике, если ты принял решение о переопределении одноимённого статического метода в классе наследнике (с приставкой new, компилятор тебе напомнит, если забудешь), то ты поступил так именно с целью использовать его _вместо_ аналогичного базового. И грабли тут как раз в явном специфицировании типа, ибо если ты скопируешь/перенесешь код в класс-наследник при рефакторинге, то он будет работать неправильно в контексте наследника, для которого ты _намеренно_ переопределил обсуждаемый статический метод.
... << 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[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[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. правила реализации методов сравнения.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.