_>Я вообще статические методы стараюсь писать со спецификацией типа, во избежании недоразумений. Если можно легко избежать лишнего бага, зачем его не избегать?
Не на том уровне "избегание багов" у тебя происходит.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, anton_t, Вы писали:
_>>Я вообще статические методы стараюсь писать со спецификацией типа, во избежании недоразумений. Если можно легко избежать лишнего бага, зачем его не избегать?
V>Не на том уровне "избегание багов" у тебя происходит.
Здравствуйте, 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.
Здравствуйте, 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.
. Понятно, что перегруженный оператор сравнения (ессно, рассматриваем случай именно с перегруженным оператором). А вот что произойдет: возвращаемое значение может оказаться отличным от проверки
myObj1 == null
. А это было бы совсем неправильно.
Так что надо просто корректно реализовывать оператор сравнения, чтобы там в первой же строке проверялось равенство на null (чтобы не вызывался лишний код). Но кто за этим будет следить, если даже в Микрософт плохо реализуют эти операторы.
Уж лучше бы вообще отказались от перегрузки операторов и пользовались методами CLS-совместимыми аналогами перегаруженных операторов (ну, там static Equals, Add, Divide и и т.д.).
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, anton_t, Вы писали:
_>>Я вообще статические методы стараюсь писать со спецификацией типа, во избежании недоразумений. Если можно легко избежать лишнего бага, зачем его не избегать?
_FR>Так вот я тебя о том и спрашиваю, хоть раз тебе удалось избежать подобного бага со статическими методами, объявленными в Object? А с методами в других классах фреймворка? А с методами собственных классов?
Я откуда знаю, я же его избежал. Тебе что не нравится-то?
Здравствуйте, anton_t, Вы писали:
_>Можно ли каким-нибудь образом заказать журнал по интернету? http://rsdn.ru/RsdnMag/Subscribe/OrderPost.aspx который месяц (если не который год) не работает.
Здравствуйте, _FRED_, Вы писали:
V>>Никаких "нет", operator== статический, т.е. тебе всё-равно придётся проверять на null первый аргумент (ссылочного типа, напомню). В общем, разница тут будет только в том случае, если твой operator== содержит баги.
_FR>Разница в том, что при одних аргументах (переменные) будет выполняться один код, а при других (null) — другой.
Можно было бы принять соглашение, что при сравнении с null производится автоматическое приведение типов к object. Это убрало бы часть граблей и сделало бы поведение интуитивно понятнее.
Видно же, что море людей ходят по этим граблям. Зачем их защищать?
ЗЫ
Вообще-то, лучше всего было бы изменить саму схему реализации операторов сравнения. Скажем если реализован метод Equals<X> для некого типа, то автоматически предоставлять возможность сравнения объекта этого типа с X по средством оператора == и !=.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, 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.
_FR>Аргументы к чему? Мы же ни о чём реальном не говорим. У меня нет оснований считать, что когда либо будет сделано так, как ты тут предлагаешь, так что и аргументировать нечего Это тебе, если хочется убедиться в своей правоте, следует завести тикет на connect-те и привести свои аргументы менеджерам из МС
Жаль, что вышла такая бесполезная дисскуссия. Вопрос был: "почему бы не заменить одну конструкцию на другую, семантически эквивалентную"? Твой ответ был потрясающий: "потому что это будет другая конструкция". На самом деле мне были интересны размышления и обмен мнениями о возможных граблях — может я что-нибудь упустил. Как правильно заметил Влад, null — это нетипизированное значение, и при сравнении с ним ссылочного типа можно приводить к object.
Здравствуйте, anton_t, Вы писали:
V>>Не на том уровне "избегание багов" у тебя происходит.
_>Это на каком "не на таком"?
Это надо на уровне дизайна класса решать, а не в строках кода.
Объясни, как у тебя вообще может получиться, что в области видимости статического метода без явного указания типа (т.е. в коде определяющего объекта или наследника) может быть случайно вызван не тот метод?
По логике, если ты принял решение о переопределении одноимённого статического метода в классе наследнике (с приставкой new, компилятор тебе напомнит, если забудешь), то ты поступил так именно с целью использовать его _вместо_ аналогичного базового. И грабли тут как раз в явном специфицировании типа, ибо если ты скопируешь/перенесешь код в класс-наследник при рефакторинге, то он будет работать неправильно в контексте наследника, для которого ты _намеренно_ переопределил обсуждаемый статический метод.
_FR>+1 Но не на основании наличия метода, а реализации интерфейса IEquatable<>. Ещё и операторы сравнения генерить автоматом, если реализован IComparable<>…
Resharper как раз любезно подсвечивает эту ситуацию и предлагает сам реализовать == и !=, а для IComparable еще и GetHashCode().
SA>Так что надо просто корректно реализовывать оператор сравнения, чтобы там в первой же строке проверялось равенство на null (чтобы не вызывался лишний код).
Несомненно! В текущей ситуации на C# по другому и быть не может. Просто есть шанс, что статью читают будущие разработчики нового мега-языка который после нашей смерти (например ) завоюет всемирную любовь. Так вот если он сделает выводы и умудрится не заложить подобные грабли в этот новый язык, то лично я буду счастлив.
SA> Но кто за этим будет следить, если даже в Микрософт плохо реализуют эти операторы.
Дык, на то и нужно живое описание проблемы. Ведь оповещен значит вооружен!
SA>Уж лучше бы вообще отказались от перегрузки операторов и пользовались методами CLS-совместимыми аналогами перегаруженных операторов (ну, там static Equals, Add, Divide и и т.д.).
Это тоже не очень хороший выход. Все же читабельность понижается. Лучшим выходом было бы изменить принципы определения операторов и ввести в язык средства предотвращения наступания на грабли (особенно на распространенные). Вот тот же запрет на сравнение с null типов определяющих операторы сравнения дал бы очень многое.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
SA>>Уж лучше бы вообще отказались от перегрузки операторов и пользовались методами CLS-совместимыми аналогами перегаруженных операторов (ну, там static Equals, Add, Divide и и т.д.).
VD>Это тоже не очень хороший выход. Все же читабельность понижается. Лучшим выходом было бы изменить принципы определения операторов и ввести в язык средства предотвращения наступания на грабли (особенно на распространенные).
Согласен. VD> Вот тот же запрет на сравнение с null типов определяющих операторы сравнения дал бы очень многое.
Да, это было бы элегантным решением. Причем, в существующем C#-стиле, когда компилятор запрещает какую-либо граблеопасную конструкцию для компиляции с выдачей соответствующих предупреждения и рекомендации.
Например:
сравнение myObj == null (с нетипизированным null) недопустимо, т.к класс MyObj реализует оператор ==. Выполните приведение к object ((object)myObj == null) или вызовите ReferenceEquals
Влад, не знаю говорили Вам уже или нет (облом всю ветку читать).
Сегодня получили новый журнал #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.
Я прав?
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;
}
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 будет вызвано вот так?
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. Что за глупость? Метод должен сгенерировать исключение с сообщением а-ля "неверный тип"!
Здравствуйте, 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]: Багодром: Реализация операторов сравнения в избранное 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. правила реализации методов сравнения.