Здравствуйте, Eldar9x, Вы писали:
E>Вот, думаю... Для удобства почти во всех классах пишу:
Главный вопрос в том, для чьего "удобства" это делается: для удобства чтения или для удобства написания?
Очевидно, что у вас есть опыт разработки на языках С/С++, в которых использовалась именно эта запись для проверки на null. Если это так, то на первое время повысится как удобство чтения, так и удобство написания. Кстати, заимствование идиом из других языков является отличной идеей, но есть ли выигрыш в данном случае, ИМХО, не уверен.
Если же это только ради удобства написания, то такое удобство должно идти лесом перед удобством чтения. Мы, все же, тратим на чтение уже написанного кода на порядок больше времени, нежели на его написание. Так что оптимизировать нужно "понятность", которая, ИМО, в данном случае хуже, поскольку нужно лезть в код и думать, а как же именно устроено неявное преобразование к bool, ведь совсем не обязательно у этого преобразования только одна семантика.
Вот какие "за" и "против" мне приходят в голову по этому поводу:
Pros:
— код читабельней разработчикам С/С++
Cons:
— diversity. Если не все будут следовать этой идиоме в проекте, что вполне возможно, то такое разнообразие будет точно минусом и предыдущий единственный плюс пойдет лесом.
— код менее читабельный всем остальным ибо не идиоматичный для языка C#. Есть мнение, что неявные преобразования — это зло, поскольку нифига не понятно, что происходит за кулисами; это было справедливо даже в С++ и не менее справедливо в C#.
— захламление кода ненужными деталями. Это ж надо каждому своему классу такую штуку приколбасить; как-то не здорово это.
— diversity (да, знаю, что это уже было, но причина тут другая). Есть мысли как делать неявное преобразование к bool встроенных типов? Если нет, то для части классов у вас все еще будет if (someVal != null), а для другой: if(anotherVal). Мне было бы неприятно читать разный код в разных местах и думать, как мне проверять для этого конкретного случая;
— существует масса других способов решения этой же проблемы: всякие Code Contract и другие велики побольше и поменьше призванные бороться с проблемой, которую Тони Хоар назвал "своей ошибкой на миллиард долларов".
Здравствуйте, Аноним, Вы писали:
А>Как же люди код на C++ сопровождают?
Ответ в вопросе: они сопровождают код на C++, и там это норма, а в C# — нет. "Здесь так принято", ага.
Вам дали сопровождать код, написанный ТС'ом. Вы ничего не знаете о его привычке создавать оператор неявного преобразования к Boolean, спросить не можете, потому что он уволился за месяц до вашего найма, задокументировать свою привычку он забыл.
Глядя на этот фрагмент кода, какое предположение о типе переменной info вы сделаете?
var info = GetDetailInfo();
if (info) // вроде Boolean
{
Debug.WriteLine(info.ToString());
// ...
}
Теперь вы читаете код дальше и видите другую строчку:
ValidateInfo(info); // хм, нафига делать валидацию Boolean?
а потом еще:
if (info.IsValid()) // блин, у Boolean точно нет метода IsValid,
// может быть, это extension?
{
// ...
}
В итоге вы лезете в определение типа и обнаруживаете там оператор приведения к Boolean.
Да, есть IntelliSense, да есть явное указание типа переменной (что не всегда удобно и можно забыть, какой у нее тип, если метод достаточно длинный), но это все равно лишние телодвижения. Ради чего?
Еще 5 копеек о преобразовании типов. Кмк, идеологически, преобразование типов — это преобразование данных, т.е. состояния объектов с использованием какой-то закономерности. В том, что делает ТС, преобразования состояния объекта нет, оно не анализируется, а в случае с null просто не может быть проанализировано. Т. е. отверткой забиваются гвозди.
От себя добавлю, что вас будут ненавидеть те, кому придется сопровождать код написанный вами.
Они долго будут смотреть на какое-нибудь условие и понимать, почему же оно вообще компилируется.
Здравствуйте, b-3, Вы писали:
E>>Нет ли тут подводных камней? b-3>Есть. Шарп — это не тот язык, на которой можно писать коротко. Шарп — это язык, на котором можно писать код, легко поддерживаемый и понятный другому разработчику с первого взгляда. b-3>Поэтому замена if (obj != null) на if (obj) духу языка очевиднейшим образом не соотвествует. Как и переименование функций "покороче" (bool SupportsTransaction { get; } в bool Trans ), как и кодогенерация самописными утилитами, как и разведение всевозможного "сахара" и "магии"
Даешь очередной виток флейма var vs "явное указание типа".
Здравствуйте, Eldar9x, Вы писали:
E>Ну... по-моему, намного лаконичней смотрится. Не понимаю, почему нет неявного приведения базовых типов к bool в C#... E>Все это как-то, громоздко что ли, смотрится:
E>
Здравствуйте, hardcase, Вы писали:
H>Заодно читаться будет легко, исчезнет возможность передать объект туда, где нужен bool, а также будет работать со встроенными типами (кроме Nullable<T>).
Вы считаете, что
if (obj.IsNull())
чем-то лучше, чем
if (obj == null)
?
Кроме того, если не ошибаюсь, FDG рекомендует бросать ArgumentException из extension-методы, если он вызван у null-а.
Здравствуйте, Eldar9x, Вы писали:
E>Вот, думаю... Для удобства почти во всех классах пишу: E> public static implicit operator bool(AnyClass anyCalss)
E>Нет ли тут подводных камней?
Есть. Шарп — это не тот язык, на которой можно писать коротко. Шарп — это язык, на котором можно писать код, легко поддерживаемый и понятный другому разработчику с первого взгляда.
Поэтому замена if (obj != null) на if (obj) духу языка очевиднейшим образом не соотвествует. Как и переименование функций "покороче" (bool SupportsTransaction { get; } в bool Trans ), как и кодогенерация самописными утилитами, как и разведение всевозможного "сахара" и "магии"
Купите Вашим разработчикам студию с интеллесенсом, а если не поможет — то курс "Соло на клавиатуре". На стоимости поддержки кода окупится
Здравствуйте, hardcase, Вы писали:
L>>
H>Я считаю что это лучше чем оператор неявного преобразования в bool. Автор говорил про читабельность — в моем варианте она на высоте.
Eldar9x-а хотя бы можно было понять — его вариант короче и для какой-то публики привычнее. Ваш же вариант, на первый взгляд, не обладает ни одним преимуществом перед банальным сравнение с null-ом.
Здравствуйте, Eldar9x, Вы писали:
E>Вот, думаю... Для удобства почти во всех классах пишу:
Если уж засахаривать, то так:
public static class ObjectExtensions
{
public static bool IsNull<T>(this T obj) where T : class
{
return null == obj;
}
public static bool IsNotNull<T>(this T obj) where T : class
{
return null != obj;
}
}
Заодно читаться будет легко, исчезнет возможность передать объект туда, где нужен bool, а также будет работать со встроенными типами (кроме Nullable<T>).
Здравствуйте, _d_m_, Вы писали:
HL>>В итоге вы лезете в определение типа и обнаруживаете там оператор приведения к Boolean.
___>+500 ___>Этот индусский авнокод из-за нескольких символов ухудшает читаемость over 9000. ___>
Не, индусский выглядел бы вот так:
if ((info != null).ToString().ToLower() == "true")
Здравствуйте, Lloyd, Вы писали:
b-3>>Поэтому замена if (obj != null) на if (obj) духу языка очевиднейшим образом не соотвествует. L>Даешь очередной виток флейма var vs "явное указание типа".
Я удивлён, как ещё в какой-нибудь Resharper не встроили рефакторинг с заменой var
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, _d_m_, Вы писали:
HL>>>В итоге вы лезете в определение типа и обнаруживаете там оператор приведения к Boolean.
___>>+500 ___>>Этот индусский авнокод из-за нескольких символов ухудшает читаемость over 9000. ___>>
L>Не, индусский выглядел бы вот так:
L>
Ну... по-моему, намного лаконичней смотрится. Не понимаю, почему нет неявного приведения базовых типов к bool в C#...
Все это как-то, громоздко что ли, смотрится:
Здравствуйте, SergeyT., Вы писали:
ST>Здравствуйте, Eldar9x, Вы писали:
E>>Вот, думаю... Для удобства почти во всех классах пишу:
ST>Главный вопрос в том, для чьего "удобства" это делается: для удобства чтения или для удобства написания? ST>Очевидно, что у вас есть опыт разработки на языках С/С++, в которых использовалась именно эта запись для проверки на null. Если это так, то на первое время повысится как удобство чтения, так и удобство написания. Кстати, заимствование идиом из других языков является отличной идеей, но есть ли выигрыш в данном случае, ИМХО, не уверен.
ST>Если же это только ради удобства написания, то такое удобство должно идти лесом перед удобством чтения. Мы, все же, тратим на чтение уже написанного кода на порядок больше времени, нежели на его написание. Так что оптимизировать нужно "понятность", которая, ИМО, в данном случае хуже, поскольку нужно лезть в код и думать, а как же именно устроено неявное преобразование к bool, ведь совсем не обязательно у этого преобразования только одна семантика.
ST>Вот какие "за" и "против" мне приходят в голову по этому поводу: ST>Pros: ST>- код читабельней разработчикам С/С++ ST>Cons: ST>- diversity. Если не все будут следовать этой идиоме в проекте, что вполне возможно, то такое разнообразие будет точно минусом и предыдущий единственный плюс пойдет лесом. ST>- код менее читабельный всем остальным ибо не идиоматичный для языка C#. Есть мнение, что неявные преобразования — это зло, поскольку нифига не понятно, что происходит за кулисами; это было справедливо даже в С++ и не менее справедливо в C#. ST>- захламление кода ненужными деталями. Это ж надо каждому своему классу такую штуку приколбасить; как-то не здорово это. ST>- diversity (да, знаю, что это уже было, но причина тут другая). Есть мысли как делать неявное преобразование к bool встроенных типов? Если нет, то для части классов у вас все еще будет if (someVal != null), а для другой: if(anotherVal). Мне было бы неприятно читать разный код в разных местах и думать, как мне проверять для этого конкретного случая; ST>- существует масса других способов решения этой же проблемы: всякие Code Contract и другие велики побольше и поменьше призванные бороться с проблемой, которую Тони Хоар назвал "своей ошибкой на миллиард долларов".
ST>Так что, ИМХО, это того не стоит.
Именно! В том то и дело, что такой код легче читать. Ну, мне по крайней мере... Тогда как
Здравствуйте, MaLS, Вы писали:
MLS>Здравствуйте, Eldar9x, Вы писали:
E>>Ну... по-моему, намного лаконичней смотрится. Не понимаю, почему нет неявного приведения базовых типов к bool в C#... E>>Все это как-то, громоздко что ли, смотрится:
E>>
Здравствуйте, Eldar9x, Вы писали:
ST>>Так что, ИМХО, это того не стоит. E>Именно! В том то и дело, что такой код легче читать. Ну, мне по крайней мере... Тогда как
obj != null
мозолит глаза .
Кажется вы для себя уже все решили. Тогда зачем было спрашивать.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[4]: Проверка объекта на null
От:
Аноним
Дата:
28.12.11 21:35
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:
КД>Здравствуйте, Аноним, Вы писали:
А>>Как же люди код на C++ сопровождают?
КД>Не знаю кто как, но я в плюсовом коде стараюсь явно сравнивать с NULL.
Я имел в виду, что когда я в незнакомом коде на C++ вижу ==, >> и т.п. я на самом деле не знаю, что он там делает. Ведь cout << 3 не сдвигает cout на три бита.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, hardcase, Вы писали:
L>Кроме того, если не ошибаюсь, FDG рекомендует бросать ArgumentException из extension-методы, если он вызван у null-а.
У нас есть целый набор extension-методов, которые, скажем так, null-safe -- им все равно, null на вход дали или нет. Очень помогает в жизни. Но они обычно имеют суффикс Safe, чтобы было понятно, что им на вход можно null передавать.
У меня давно сидит в голове одна мысль, связанная с тем, что причина некоторых "тормозов" .Net связана не только с GC и JIT, но и с подобными проверками в всех возможных местах стандартной библиотеки.
Вот в C++ это бы проверяли (если бы вообще проверяли) в отладочной версии СRT (ну или MFC), а в Release все эти ASSERT просто бы исчезли.
Ну вот, например, нафига WPF уже в отлаженной и без ошибок работающей программе постоянно проверяет "а мы вызваны из того же потока, из которого созданы?".
Я понимаю, что проверка аргумента функции на null и выдача ArgumentNullException более информативна для определения причины ошибки, чем NullReferenceException (которая может значить что угодно), но в отлаженной программе, переданной заказчику ошибок ArgumentNullException быть не должно. В общем, я хочу Release-версию .Net
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, hardcase, Вы писали:
H>>Заодно читаться будет легко, исчезнет возможность передать объект туда, где нужен bool, а также будет работать со встроенными типами (кроме Nullable<T>).
L>Вы считаете, что L>
L>if (obj.IsNull())
L>
L>чем-то лучше, чем L>
L>if (obj == null)
L>
L>?
L>
Я считаю что это лучше чем оператор неявного преобразования в bool. Автор говорил про читабельность — в моем варианте она на высоте.
А в целом вот эти два варианта одна фигня.
L>Кроме того, если не ошибаюсь, FDG рекомендует бросать ArgumentException из extension-методы, если он вызван у null-а.
Какой FDG в контексте этого топика? Хотя пускай лучше авторы FDG подумают как сделать non-null ссылочные типы, а не обходить грабли которые сами же и положили...
Здравствуйте, Doc, Вы писали:
Doc>Здравствуйте, Eldar9x, Вы писали:
ST>>>Так что, ИМХО, это того не стоит. E>>Именно! В том то и дело, что такой код легче читать. Ну, мне по крайней мере... Тогда как
obj != null
мозолит глаза .
Doc>Кажется вы для себя уже все решили. Тогда зачем было спрашивать.
Ну, почему же? В С# я совсем не спец, поэтому и интересуюсь. К примеру, с private protected полями меня здесь убедили, что лучше делать их только private, и далее я так буду писать. Также и с этим вопросом получается не все так однозначно.
Здравствуйте, Eldar9x, Вы писали:
E>Ну, почему же? В С# я совсем не спец, поэтому и интересуюсь.
Так уже пояснили причину. Если вы пишете код не только для себя, то другим разработчикам будет трудно понять о чем речь. Я бы тоже предпочел явное сравнение, причем даже в С/C++, хоть и писать больше. Зато сразу видно о чем речь.
Здравствуйте, HowardLovekraft, Вы писали:
HL>Глядя на этот фрагмент кода, какое предположение о типе переменной info вы сделаете?
... HL>В итоге вы лезете в определение типа и обнаруживаете там оператор приведения к Boolean.
+500
Этот индусский авнокод из-за нескольких символов ухудшает читаемость over 9000.
Здравствуйте, aloch, Вы писали:
A>Ну вот, например, нафига WPF уже в отлаженной и без ошибок работающей программе постоянно проверяет "а мы вызваны из того же потока, из которого созданы?".
Скорей всего потому, что без проверки и если действительно вызваны из другого потока, то получаем у клиента загадочные и слабовоспроизводимые баги типа мемори коррупшион.
b-3>Поэтому замена if (obj != null) на if (obj) духу языка очевиднейшим образом не соотвествует. Как и переименование функций "покороче" (bool SupportsTransaction { get; } в bool Trans ), как и кодогенерация самописными утилитами, как и разведение всевозможного "сахара" и "магии"
b-3>Купите Вашим разработчикам студию с интеллесенсом, а если не поможет — то курс "Соло на клавиатуре". На стоимости поддержки кода окупится
Здравствуйте, b-3, Вы писали:
L>>Даешь очередной виток флейма var vs "явное указание типа".
b-3>Я удивлён, как ещё в какой-нибудь Resharper не встроили рефакторинг с заменой var
Здравствуйте, b-3, Вы писали:
b-3>Здравствуйте, Lloyd, Вы писали:
b-3>>>Поэтому замена if (obj != null) на if (obj) духу языка очевиднейшим образом не соотвествует. L>>Даешь очередной виток флейма var vs "явное указание типа".
b-3>Я удивлён, как ещё в какой-нибудь Resharper не встроили рефакторинг с заменой var
Однако в некоторых случаях лучше вар:
Dictionary<string, SuperPuperMegaTip> asd = new Dictionary<string, SuperPuperMegaTip>();
// илиvar asd = new Dictionary<string, SuperPuperMegaTip>();
Здравствуйте, _d_m_, Вы писали:
___>Однако в некоторых случаях лучше вар: ___>
Dictionary<string, SuperPuperMegaTip> asd = new Dictionary<string, SuperPuperMegaTip>();
// илиvar asd = new Dictionary<string, SuperPuperMegaTip>();
Не в "некоторых", а в тех, в которых тип написан где-то рядом.
Есть люди, пишущие так:
class MyClass
{
var member = FooInit();
/* на 5 экранов ниже */static ILookup<string, IDictionary<MyPODKey, object>> FooInit() { /* ... */ }
}
В особо запущенных случах попытка поговорить об этом приводит к жалобам на "какой плохой язык C#, что нельзя написать static var FooInit()" и в пример ставится какой-нибудь F#/Haskell Хотя на самом деле тут дело в неумении использовать статическую типизацию.
Здравствуйте, b-3, Вы писали:
b-3>В особо запущенных случах попытка поговорить об этом приводит к жалобам на "какой плохой язык C#, что нельзя написать static var FooInit()" и в пример ставится какой-нибудь F#/Haskell Хотя на самом деле тут дело в неумении использовать статическую типизацию.
Причем тут неумение использовать статическую типизацию, если var не отменяет статическую типизацию?
И модификатор static (var) к статической типизации отношения не имеет.
Здравствуйте, samius, Вы писали:
S>Здравствуйте, b-3, Вы писали:
b-3>>В особо запущенных случах попытка поговорить об этом приводит к жалобам на "какой плохой язык C#, что нельзя написать static var FooInit()" и в пример ставится какой-нибудь F#/Haskell Хотя на самом деле тут дело в неумении использовать статическую типизацию.
S>И модификатор static (var) к статической типизации отношения не имеет.
Я про глобальное выведение типов, которого в C# нет, а некоторым хочется. В частности, чтобы не писать типы возвращаемых значений у функций (var Foo()).
S>Причем тут неумение использовать статическую типизацию, если var не отменяет статическую типизацию?
При том, что статическая типизация существует не только для того, чтобы осложнить жизнь программисту и заставить его писать лишние буквы. Я правильно понял, что вы считаете пример с FooInit нормальным кодом?
Здравствуйте, b-3, Вы писали:
b-3>Здравствуйте, samius, Вы писали:
S>>Здравствуйте, b-3, Вы писали:
b-3>>>В особо запущенных случах попытка поговорить об этом приводит к жалобам на "какой плохой язык C#, что нельзя написать static var FooInit()" и в пример ставится какой-нибудь F#/Haskell Хотя на самом деле тут дело в неумении использовать статическую типизацию.
S>>И модификатор static (var) к статической типизации отношения не имеет. b-3>Я про глобальное выведение типов, которого в C# нет, а некоторым хочется. В частности, чтобы не писать типы возвращаемых значений у функций (var Foo()).
Я просто увидел в соседних предложениях слова static и "неумение использовать статическую типизацию". И подумал, что они как-то связаны между собой.
Кстати, и вывыедение типа по инициализации, и вывод типа результата функции в С# есть. Просто они не везде разрешены.
S>>Причем тут неумение использовать статическую типизацию, если var не отменяет статическую типизацию? b-3>При том, что статическая типизация существует не только для того, чтобы осложнить жизнь программисту и заставить его писать лишние буквы.
Причем здесь статическая типизация, если она есть как с var, так и без него? C#, F#, Haskell — это статически типизированные языки, если не считать dynamic из C#.
b-3>Я правильно понял, что вы считаете пример с FooInit нормальным кодом?
Смотря в каком контексте.
Вообще — var и () там лишние. Но и выкидывать их из C# я бы не спешил.
Здравствуйте, aloch, Вы писали:
A> нафига WPF уже в отлаженной и без ошибок работающей программе постоянно проверяет "а мы вызваны из того же потока, из которого созданы?".
Таких программ не существует. Это миф. Поэтому и проверяет. Может и сами поймете, когда через год-другой придется расширять UI
Как известно, 90% людей верят утверждениям, начинающимся со слов «как известно».
Здравствуйте, __gas, Вы писали:
__>Здравствуйте, aloch, Вы писали:
A>> нафига WPF уже в отлаженной и без ошибок работающей программе постоянно проверяет "а мы вызваны из того же потока, из которого созданы?".
__>Таких программ не существует. Это миф. Поэтому и проверяет. Может и сами поймете, когда через год-другой придется расширять UI
В WPF все гораздо хуже чем проверки потоков. В XAML связывание данных динамическое, изза при изменении свойств в классах пожно получить фигню не при компиляции, а в рантайме.
Кстати, вот пример реального кода (и правда индусского), который проверяет некоторое свойство на null:
if (obj.SomeProp.ToString() == null)
{
commandParams.Add("@some_prop", typeof(string));
log.Error("SomeProp is null for object with id" + obj.SomeId.ToString());
}
И человек, кстати, очень удивился, когда я ему сказал, что это работать не будет
Здравствуйте, _d_m_, Вы писали:
___>Здравствуйте, Lloyd, Вы писали:
L>>Здравствуйте, _d_m_, Вы писали:
HL>>>>В итоге вы лезете в определение типа и обнаруживаете там оператор приведения к Boolean.
___>>>+500 ___>>>Этот индусский авнокод из-за нескольких символов ухудшает читаемость over 9000. ___>>>
L>>Не, индусский выглядел бы вот так:
L>>