Комментарии 21
«No matter what type is involved, a == a is always true.»
На самом деле, для платформы .NET это правило исполняется не всегда. А вы можете привести пример, когда это условие нарушается?
double.NaN == double.NaN
Или когда оператор переопределён и возвращает true/false в зависимости от Random :)
class Program {
static int cntr=0;
static int a { get { return ++cntr; } }
static void Main(string[] args) {
Console.WriteLine("{0}",a==a);
}
}
Напечатала false. Безо всяких переопределений сравнения.
>> Любой программист, пришедший в .NET из С++ ответит положительно (ведь так быстрее!), потом он прочитает о проблемах и его мнение наверняка изменится на противоположное.
Ни один программист пришедший из c++ никогда не изменит свое мнение. В с++ это не считается проблемами, в с++ весь геморой которым борешься пол жизни считается наградой, выслугой лет.
А те кто изменяет свое мнение (например после шарпа), никогда не возвращается назад в с++.
Ни один программист пришедший из c++ никогда не изменит свое мнение. В с++ это не считается проблемами, в с++ весь геморой которым борешься пол жизни считается наградой, выслугой лет.
А те кто изменяет свое мнение (например после шарпа), никогда не возвращается назад в с++.
Неточность #3. Об операторе ==
«No matter what type is involved, a == a is always true.»
Это предложение не является неточностью, оно очень неудачно выдернуто из контекста:
… you need to keep in mind the mathematical properties of equality: Equality is reflexive, symmetric, and transitive. The reflexive property means that any object is equal to itself. No matter what type is involved, a == a is always true.
То есть
a == a is always trueэто всего лишь определение рефлексивности.
Вообще же автор пишет о том, как должен работать оператор сравнения в том случае если программист решит его переопределить, а не о том как он на самом деле работает.
Спасибо за добавление контекста, в этом случае неточность становится более четкой:) Дело в том, что в .NET-е, рефлексивность обязан обеспечивать метод Equals, но ее нет у оператора ==.
Это одна из причин (помимо того, что оператор == не полиморфный), почему для определения эквивалентности объектов в том же Dictionary используется именно Equals, а не оператор ==.
И Double.NaN является известным примером, когда Equals остается рефлексивным, а оператор == — нет.
Это одна из причин (помимо того, что оператор == не полиморфный), почему для определения эквивалентности объектов в том же Dictionary используется именно Equals, а не оператор ==.
И Double.NaN является известным примером, когда Equals остается рефлексивным, а оператор == — нет.
Если я не ошибаюсь, NaN по стандарту себе не равен, и не только для C#, что предполагает, что NaN не принадлежит типу, для которого должна обеспечиваться рефлексивность.
double.NaN хитрый зверь:
double.NaN.Equals(double.NaN) — true
double.NaN == double.NaN — false
Просто если бы не работал Equals, то вы бы не смогли из словаря double.NaN достать.
double.NaN.Equals(double.NaN) — true
double.NaN == double.NaN — false
Просто если бы не работал Equals, то вы бы не смогли из словаря double.NaN достать.
Equals видимо не подпадает видимо под действие стандарта.
На википедии, кстати, написано, NaN себе не равен по стандарту IEEE 754. И там кстати также написано, почему так. NaN может быть получен от деления на ноль, от извлечения корня из отрицательного числа, и т.п. Записывается результат одинаково, а вот получить равенство результатов вышеперечисленных операций было бы фейлом.
Так что с рефлексивностью у оператора == все в порядке.
На википедии, кстати, написано, NaN себе не равен по стандарту IEEE 754. И там кстати также написано, почему так. NaN может быть получен от деления на ноль, от извлечения корня из отрицательного числа, и т.п. Записывается результат одинаково, а вот получить равенство результатов вышеперечисленных операций было бы фейлом.
Так что с рефлексивностью у оператора == все в порядке.
Неточность #5. Порядок создания объектовВыглядит как вырванное из контекста. Ну т.е. при создании экземпляра операции действительно выполняются в таком порядке. Аналогично:
1. Static variable storage is set to 0.— если статических членов нет, то и устанавливаться в ноль ничего не будет.
Речь немного не об этом. Речь о выделенном, что при создании экземпляра вначале вызывается статический конструктор базового класса, а потом статический конструктор наследника. В некоторых случаях (при наличии атрибута beforefieldinit у типа), при создании экземпляра наследника даже вызов статического конструктора наследника не гарантируется (подробности здесь).
Но даже в базовом случае, порядок вызова статических конструкторов противоположен порядку вызова экземплярных конструкторов: экземплярные конструкторы взываются от базового к наследнику, а статические конструкторы — от наследника к базовому.
Вот пруф:
При вызове new Derived() на экране мы получим следующее:
Но даже в базовом случае, порядок вызова статических конструкторов противоположен порядку вызова экземплярных конструкторов: экземплярные конструкторы взываются от базового к наследнику, а статические конструкторы — от наследника к базовому.
Вот пруф:
internal class Base
{
public Base()
{
Console.WriteLine("Base.ctor");
}
static Base()
{
Console.WriteLine("Base.cctor");
}
}
internal class Derived : Base
{
public Derived()
{
Console.WriteLine("Derived.ctor");
}
static Derived()
{
Console.WriteLine("Derived.cctor");
}
}
При вызове new Derived() на экране мы получим следующее:
Derived.cctor
Base.cctor
Base.ctor
Derived.ctor
Я в свое время заказал на Амазоне и Скита, и Вагнера в одной посылке. Сначала прочитал Скита и был в диком восторге. А потом прочитал Вагнера и остался разочарован. Мне не понравилась ультимативность стиля изложения как таковая. Некоторые советы показались надуманными. И да, минимум объяснений на контрасте со Скитом смотрелось очень неинтересно. Книга имеет право на жизнь, но почему она стоит столько же, сколько и «C# in Depth», я не понимаю.
мой совет: сначала прочитать CLR via C#, а потом уже Effective C#, и при расхождениях верить первой книжке.
А что может автор данной статьи рассказать о плюсах данной книги? Указанные недочеты — это не вся книга.
Из плюсов: довольно приличное количество мыслей для размышлений, разбитых по разделам. Начинаешь читать главы по Equals/GetHashCode, любые несогласия с автором вынуждают к определенному ресерчу, который позволяет понять, где же на самом деле правда. И таких «вбросов» достаточно много; на часть из них сам автор дает вменяемые ответы, а вот ответы на другие вбросы придется искать в другом месте.
Возможно недостатки подпортили впечатление сильнее, в результате чего положительные моменты не так сильно отпечатались в памяти. Все будет зависеть от того, что вы читали до этого. Если для вас в книге Скита не много нового, то эту книгу нет смысла читать. Если же у вас пара лет опыта работы с платформой .NET и языком C#, то в книге Вагнера будет много полезного.
Возможно недостатки подпортили впечатление сильнее, в результате чего положительные моменты не так сильно отпечатались в памяти. Все будет зависеть от того, что вы читали до этого. Если для вас в книге Скита не много нового, то эту книгу нет смысла читать. Если же у вас пара лет опыта работы с платформой .NET и языком C#, то в книге Вагнера будет много полезного.
А русскоязычный вариант есть?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
О книге Билла Вагнера «Effective C#»