C # Антипаттерны

Короче говоря: я считаю антипаттернов Java незаменимым ресурсом. Как для новичков, так и для профессионалов. Мне еще предстоит найти что-то подобное для C #. Итак, я открою этот вопрос как вики сообщества и приглашаю всех поделиться своими знаниями по этому поводу. Поскольку я новичок в C #, меня это сильно интересует, но я не могу начать с некоторых антипаттернов: /

Вот ответы, которые я считаю верными для C #, а не для других языков.

Я просто скопировал / вставил их! Также подумайте о комментариях к ним.


Бросок NullReferenceException

Выбрасывание неправильного исключения:

if (FooLicenceKeyHolder == null)
    throw new NullReferenceException();

Свойства и общедоступные переменные

Открытые переменные в классах (вместо этого используйте свойство).

Если класс не является простым объектом передачи данных.


Непонимание того, что bool - это реальный тип, а не просто соглашение

if (myBooleanVariable == true)
{
    ...
}

или, что еще лучше

if (myBooleanVariable != false)
{
    ...
}

Подобные конструкции часто используются C и C++ разработчиками, где идея логического значения была просто условностью (0 == ложь, все остальное верно); в C # или других языках с настоящими логическими значениями это не обязательно (или нежелательно).


Использование using()

Не использовать using там, где это необходимо:

object variable;
variable.close(); //Old code, use IDisposable if available.
variable.Dispose(); //Same as close.  Avoid if possible use the using() { } pattern.
variable = null; //1. in release optimised away.  2. C# is GC so this doesn't do what was intended anyway.

person Community    schedule 07.10.2009    source источник
comment
Ну ... это было именно того, чего я пытался избежать. Вопрос, связанный как дубликат, содержит много распространенных недобросовестных приемов объектно-ориентированного программирования. Я занимаюсь разработкой более 10 лет, и это для меня не новость. В этом случае я ожидал конкретных антипаттернов C #.   -  person exhuma    schedule 07.10.2009
comment
Антипаттерны Java, на которые вы ссылаетесь, - это не антипаттерны (например, неэффективные и / или контрпродуктивные шаблоны проектирования), а плохие методы кодирования, как и большинство ответов на ваш вопрос. Как и шаблоны проектирования, антипаттерны не зависят от языка.   -  person comichael    schedule 12.10.2009
comment
хорошая точка зрения. Если вы рассмотрите шаблоны проектирования, есть те, которые не зависят от языка, но тогда некоторые из них имеют больше смысла в языке, чем другие. Другие могут не иметь отношения к данному языку, если сам язык предлагает решение данной проблемы. Поэтому я предполагаю, что вы также можете найти антипаттерны, которые более актуальны для C #, чем для других языков. Повторять одни и те же хорошие / плохие практики снова и снова становится скучно;)   -  person exhuma    schedule 15.10.2009
comment
Кстати, Dispose не всегда включает Close. Это работает в большинстве классов .net, и это здравый смысл, но нигде явно не подразумевается.   -  person Michael Stum    schedule 23.12.2009


Ответы (38)


Неправильное отображение исключения. Чтобы повторно вызвать исключение:

try
{
    // do some stuff here
}
catch (Exception ex)
{
    throw ex;  // INCORRECT
    throw;     // CORRECT
    throw new Exception("There was an error"); // INCORRECT
    throw new Exception("There was an error", ex); // CORRECT
}
person Community    schedule 07.10.2009
comment
catch (Exception ex) сам по себе является антипаттерном. - person Joren; 07.10.2009
comment
Если вы не ведете журнал или что-то подобное, а затем повторно бросаете его - person thecoop; 08.10.2009
comment
@Joren, catch (Exception ex) без throw - это анти-шаблон ... есть много допустимых случаев для перехвата общего типа исключения, если вы отбрасываете (например, ведение журнала, выброс нового типа исключения, выполнение отката для некоторых ресурсы и т. д.). Но, конечно, правила различаются для приложений, библиотек, плагинов и т. Д. - person Pop Catalin; 08.10.2009
comment
catch (Exception ex) отлично подходит для веб-приложений. могут быть и другие случаи. - person Egor Pavlikhin; 08.10.2009
comment
aaah throw new Exception (Произошла ошибка, например); поэтому он показывает исходное исключение как внутреннее исключение, хорошо! - person Carlo; 08.10.2009
comment
throw new Exception (Произошла ошибка) может быть совершенно допустимым, если вы хотите скрыть исходную ошибку (например, библиотеку), возможно, связанную с безопасностью. - person erikkallen; 10.10.2009

GC.Collect() собирать вместо того, чтобы доверять сборщику мусора.

person Community    schedule 07.10.2009
comment
И не дождаться завершения ожидающих завершения в тех редких ситуациях, когда вы действительно хотите принудительно собрать коллекцию. - person Eric Lippert; 07.10.2009
comment
Не совсем. У меня были ситуации, когда я получал воспроизводимое исключение OutOfMemoryException, которое исчезало после вызова GC.Collect () время от времени. GC вроде не работает. - person Rauhotz; 08.10.2009
comment
сломанный vs недетерминированный. Если вы выпускаете много ссылок и вдруг снова нуждаетесь в них, то это, вероятно, кандидат на вызов вручную. - person Spence; 08.10.2009
comment
Я голосую за недетерминированность, по крайней мере, я бы никогда не хотел определять, что бы я делал сейчас, будь я генеральным директором. Это детали реализации, на которые нельзя полагаться. Разве в сборе одежды нет даже двухэтапного подхода? Может, стоит заменить все GC.Collect; автор: 'GC.Collect (); GC.Collect (); ' - person Simon D.; 08.10.2009
comment
Если сборщик мусора предпочитает генерировать исключение OutOfMemoryException вместо того, чтобы просто выполнять свою работу, которая собирает мусор (например, через GC.Collect) и предоставляет мне запрошенную память, я называю это неработающим. - person Rauhotz; 08.10.2009
comment
Вы можете получить OutOfMemoryException за наличие фрагментированных ссылок или за запрос большего объема памяти, чем имеется в вашей системе. У вас, случайно, есть фиксированный размер файла подкачки? Я имею в виду, что если вы думаете, что можете написать лучший сборщик мусора, чем Microsoft, я говорю, сделайте это, а затем заставьте их купить его у вас. - person Matthew Whited; 08.10.2009
comment
Есть допустимые варианты использования GC.Collect (), но почти нет их в типичных приложениях. Вам нужно специальное использование для .Net для вызова GC.Collect () (как игровой движок, после загрузки уровня, поэтому GC не запускается в середине уровня, выполняя полный сбор, собирая объекты, выделенные на предыдущем уровне) или приложений, близких к реальному времени, где поведение сборщика мусора должно быть в некоторой степени контролируемым и предсказуемым, или серверных приложений, когда вы знаете, что будете работать в режиме ожидания в течение определенного периода и использовать эту возможность для сбора. - person Pop Catalin; 08.10.2009
comment
@Pop Catalin - Все допустимые варианты использования ... Что такое нормальное приложение? Мне все это кажется нормальными приложениями. - person Robert Fraser; 25.05.2010
comment
@ Роберт Фрейзер, я никогда не использовал слово «нормальный», но «типичный», означающее то, что разработчики .Net ежедневно пишут на данный момент, но в будущем все изменится, и типичный будет включать в себя более широкий спектр, чем сейчас . - person Pop Catalin; 29.05.2010

Я слишком часто вижу это как в Java, так и в C # ...

if(something == true){
  somethingelse = true;
}

с бонусными баллами, если у него также есть

else{
  somethingelse = false;
}
person Community    schedule 07.10.2009
comment
Без бонуса это не так больно (только == правда) - person ripper234; 07.10.2009
comment
В первом случае рассмотрим случай something = false и somethingelse = true. Вы не должны выполнять рефакторинг на somethingelse = something - person vanja.; 07.10.2009
comment
Согласен с rupper234. В некоторых случаях это может улучшить читаемость. - person Egor Pavlikhin; 07.10.2009
comment
Мы можем сделать это лучше: if (something == true) {somethingelse = true; } else {somethingelse = false; } вернуть что-нибудь еще; - person Wedge; 07.10.2009
comment
кроме того, что это подробное описание, это не «ошибка» как таковая. - person Johnno Nolan; 08.10.2009
comment
видел это сегодня в The Daily WTF thedailywtf.com/Articles/The-Clever-Coder.aspx - person sstewart; 09.10.2009
comment
@Tordek - Я НИКОГДА не видел, чтобы эта конструкция использовалась. Я бы сказал, что версия if-statement более читабельна. - person Robert Fraser; 25.05.2010
comment
-1. Это более многословно, чем необходимо, но в остальном в этом нет ничего плохого. - person Joh; 25.05.2010
comment
@ Роберт Фрейзер: А, я думал о C. Более подходящим (но не существующим в C #) будет ||=. Или от руки, которую он будет представлять: somethingelse = something || somethingelse. (Это, конечно, предполагает две вещи: somethingelse имеет значение, а else не используется; в противном случае достаточно somethingelse = something /) - person Tordek; 27.05.2010

using Microsoft.SharePoint;

'достаточно

person Community    schedule 09.10.2009

Я часто вижу следующий код:

if (i==3)
       return true;
else
       return false;

должно быть:

       return (i==3);
person Community    schedule 08.10.2009
comment
Да, я все время это вижу. Я всегда реорганизую его, если у меня есть время. - person rein; 08.10.2009
comment
Что действительно плохо, так это отсутствие скобок :) - person Egor Pavlikhin; 08.10.2009
comment
Отсутствие скобок? Вы, должно быть, имеете в виду предпочтения по стилю. - person Robert Harvey; 08.10.2009
comment
Или, по крайней мере, отбросьте еще, но я предпочитаю, как вы упомянули Бенни. - person Adam Luter; 08.10.2009
comment
return не функция. Скобки не нужны. - person P Daddy; 09.10.2009
comment
@DisgruntledGoat: Мне они кажутся шумом. - person P Daddy; 06.11.2009
comment
Играя в адвоката дьявола - наверняка оба станут одинаковыми при компиляции, так что никакой разницы в скорости нет, а первая версия потенциально более читабельна для более молодых программистов? - person Kris C; 04.12.2009

Оскорбление закона Деметры:

a.PropertyA.PropertyC.PropertyB.PropertyE.PropertyA = 
     b.PropertyC.PropertyE.PropertyA;
person Community    schedule 07.10.2009
comment
+1, но, к сожалению, в некоторых случаях (особенно со статическими классами) может показаться, что от этого трудно уйти ... Например, недавно я написал это: this.Left = Screen.AllScreens[target].Bounds.X - person Matthew Scharley; 07.10.2009
comment
@matthew: меня беспокоит не столько левая сторона. Присваивание / мутация - это проблема. Звоните подскажите, что модифицируете? - person leppie; 07.10.2009
comment
Я устанавливаю левую часть моей формы на левый край целевого экрана. На самом деле Screen.AllScreens является псевдонимом локальной переменной, потому что я не хотел везде вводить полную квалификацию, но это только сокращает то, что я печатаю, не меняя намерения. - person Matthew Scharley; 07.10.2009

Бросок NullReferenceException:

if (FooLicenceKeyHolder == null)
    throw new NullReferenceException();
person Community    schedule 07.10.2009
comment
Кроме того, я думаю, что общий антипаттерн будет вручную генерировать any исключение, которое сама среда выполнения выбрасывает, когда что-то плохое происходит. - person Matthew Scharley; 07.10.2009
comment
Да, но это особенно вводит в заблуждение, потому что на самом деле это не то, что произошло. - person Ed S.; 07.10.2009
comment
Я сомневаюсь, что ArgumentNullException - это выход в этом случае, поскольку из кода не кажется, что this.FooLicenseHolder является аргументом функции (по крайней мере, это не выглядит как одно из соглашений). Возможно, если немного перефразировать код, ваша (совершенно верная) мысль станет немного яснее. - person petr k.; 08.10.2009
comment
@petr: Вы действительно правы. Это свойство, а не параметр. Что делает код еще более ужасным! - person leppie; 08.10.2009
comment
Надеюсь, мы сможем избавиться от этого с помощью кодовых контактов в .Net 4.0. - person Matthew Whited; 08.10.2009
comment
@matthew: ничто не мешает вам написать свой собственный маленький класс Contracts :) - person leppie; 08.10.2009
comment
Как насчет методов расширения? Разве не было бы хорошего места для использования исключений NullReferenceExceptions? - person Andrei Rînea; 28.10.2010

Это правда, я видел это собственными глазами.

public object GetNull()
{
     return null;
}

На самом деле он использовался в приложении, и даже имел вместе с ним хранимую процедуру, sp_GetNull, которая возвращала бы null ....

это сделало мой день.

Я думаю, что sp использовался для классического сайта asp .. что-то связано с набором результатов. в .net была идея "конвертировать" код в .net ...

person Community    schedule 07.10.2009
comment
Итак, вы инкапсулируете концепцию нулевого значения внутри функции: P - person Daniel Daranas; 08.10.2009
comment
Должно быть, они думали, что null может измениться в будущем :) - person PeteT; 05.02.2010

int foo = 100;
int bar = int.Parse(foo.ToString());

Или более общий случай:

object foo = 100;
int bar = int.Parse(foo.ToString());
person Community    schedule 07.10.2009
comment
Это ... что? Почему? -хеддеск- Ты не можешь сказать мне, что это кто-то сделал? - person Matthew Scharley; 07.10.2009
comment
Я на самом деле довольно много реорганизовал из нашей кодовой базы O_o - person Andrew Barrett; 07.10.2009
comment
@matthew: добавлен более общий случай (он же из таблицы данных, хе-хе) - person leppie; 07.10.2009
comment
Да, хорошо, я вижу, как люди делают это ради объекта. Но для int на int задание ... - person Matthew Scharley; 07.10.2009
comment
Я не шучу, я видел, как люди делали это для целых, это был один из многих WTF моментов, которые у меня были. - person Andrew Barrett; 07.10.2009
comment
Я тоже видел примеры этого, хотя, честно говоря, между ними было довольно много кода, чтобы сделать это не таким очевидным, но все же таким же глупым. - person Michael Stum; 07.10.2009
comment
Я однажды видел это в коде моего коллеги, когда делал обзор кода. Настоящая чушь ... - person Meta-Knight; 08.10.2009
comment
Я видел этот точный тип кода в приложении, которое было передано на аутсорсинг в Индию ... это приложение было полно таких WTF, на самом деле в нем были почти все анти-паттерны в этом потоке ... - person Pop Catalin; 08.10.2009
comment
lol, когда я сделал строку number = 1.ToString (); к концу дня была пятница, поэтому я не виню его = P (да, это было отстойно, когда я увидел это в следующий понедельник, мне было так стыдно) - person Carlo; 08.10.2009
comment
@Carlo: это действительно неплохая практика; 1.ToString () будет использовать настройки локали в случае, если по умолчанию 1 обычно пишется как-то иначе :) (Возможно, они получат «умную» версию номера UNICODE, так же как MS Word любит давать вам свои "умные" цитаты, когда вы их не просите) - person sehe; 13.07.2011
comment
@sehe hahaha, тогда не о чем смущаться! - person Carlo; 14.07.2011

Я нашла это в нашем проекте и чуть не сломала стул ...

DateTime date = new DateTime(DateTime.Today.Year, 
                             DateTime.Today.Month, 
                             DateTime.Today.Day);
person Community    schedule 07.10.2009
comment
Я думаю, что общий анти-шаблон просто полностью испортил использование классов DateTime / TimeSpan. - person anthony; 07.10.2009
comment
Я думаю, что отказ от использования или незнание, что такое объекты Timespan, здесь тоже хорошо. - person Spence; 07.10.2009
comment
Для записи правильное использование: DateTime date = DateTime.Now; - person Wedge; 07.10.2009
comment
или DateTime date = DateTime.ToDay; - person Adriaan Stander; 07.10.2009
comment
Разве они (Сейчас и Сегодня) не предоставят объекты даты с часами, минутами и так далее, где в примере есть только часть даты? - person svinto; 08.10.2009
comment
На самом деле правильное использование: DateTime date = DateTime.Now.Date; (или Today.Date) Если вы опустите дату, вы также получите время. - person Meta-Knight; 08.10.2009
comment
И я действительно не вижу большой проблемы с этим кодом, возможно, кодировщик просто не знал о свойстве Date ... -1 - person Meta-Knight; 08.10.2009
comment
Гм, правильное использование: Datetime date = Datetime.Now.Date - person Spence; 08.10.2009
comment
Правильно, вы всегда должны использовать конструктор с явной информацией DateTimeKind (local / UTC). - person Simon D.; 08.10.2009
comment
@astander, svinto: Правда ?? Сегодня?? Ты серьезно? Для крика вслух верблюжья оболочка действительно начинает выходить из-под контроля! Одно долбаное слово. Сегодня. - person P Daddy; 09.10.2009
comment
Видно хуже: DateTime dt = new DateTime (2001, 1, 1, TimeSpan.FromSeconds (секунды) .Hours, TimeSpan.FromSeconds (секунды) .Minutes, TimeSpan.FromSeconds (секунды) .Seconds); - person GeReV; 04.02.2010

Довольно часто я натыкаюсь на такого рода злоупотребления варом:

var ok = Bar();

или даже лучше:

var i = AnyThing();

Использование var таким образом не имеет смысла и ничего не дает. Это просто усложняет соблюдение кода.

person Community    schedule 07.10.2009
comment
Я согласен - похоже, что в последнее время var очень злоупотребляют. - person Paddy; 08.10.2009
comment
Я не вижу здесь антипаттерна, var удаляет избыточное определение типа, так как Bar () или AnyThing () всегда будет возвращать один и тот же тип. Если вы когда-нибудь измените тип возвращаемого значения Bar () или AnyThing (), например используйте интерфейс вместо реализации, вам не нужно будет менять ok и i, если им нужен только интерфейс, что хорошо. - person Simon D.; 08.10.2009
comment
Это плохо, потому что вы не можете сразу определить тип, не зная методов Bar () и AnyThing (). На мой взгляд, удобочитаемость важнее, чем сохранение нескольких повторяющихся символов. Помимо этого, var очень полезен для таких операторов: var i = new MyTypeWithVeryLongName (); Разница в том, что вы можете мгновенно распознать тип. - person Christian Schwarz; 08.10.2009
comment
это C #? На моей стороне не компилируется;) - person exhuma; 08.10.2009
comment
var something = new Something () в порядке. Вы знаете, какого типа будет объект. Еще лучше, когда var сочетается с универсальными методами для уменьшения дублирования (следует правилу DRY). - person Finglas; 08.10.2009
comment
Я не вижу в этом проблемы, если 1. Имя метода ясное и 2. Имя переменной ясно. - person Meta-Knight; 08.10.2009
comment
К сожалению, ReSharper, похоже, любит предлагать в любом объявлении переменной использовать var .. - person Jess; 08.10.2009
comment
Было бы терпимо, если бы вы могли навести указатель мыши на переменную и увидеть ее предполагаемый тип. - person Juliet; 08.10.2009
comment
@ Докеры. Вы приводите пример «Не повторяйся», но те, что в посте, больше похожи на «Не говори ничего». - person Daniel Daranas; 08.10.2009
comment
Было бы нормально, если бы это были конструкторы, но это не так. Было бы нормально, если бы это тоже были фабричные классы, если тип очевиден (например, Service.Create(...)) - person Adam Luter; 08.10.2009
comment
Я не понимаю, почему это было бы анти-шаблоном в C #, когда он, по-видимому, отлично подходит для языков вывода типов (Haskell, F # и т. Д.) И языков со слабой типизацией (JavaScript, Python и т. Д.) Или даже только так, как вы можете это сделать. - person JulianR; 09.10.2009
comment
Я бы перефразировал это, если неясно, что возвращает Something (). var person = FindPersonByAddress (адрес); мне невероятно ясно. - person Matt Briggs; 09.10.2009
comment
@Julian: Как вы думаете, почему мы используем C #, а не PHP? Они не являются антипаттернами в этих языках именно потому, что они не могут быть антипаттернами, это единственный WTDI. В C # есть больше и лучших способов сделать это. - person Matthew Scharley; 22.10.2009
comment
@Andrew Koester - Вы можете изменить это в ReSharper. Вы можете заставить его всегда предлагать фактический тип вместо var или просто заставить его замолчать - person Robert Fraser; 25.05.2010

person Community    schedule 07.10.2009
comment
Было бы полезно разделить их на отдельные ответы, которые можно было бы проголосовать за / против независимо. - person Bevan; 07.10.2009
comment
публичное событие EventHandler MyEvent = делегат {}; ‹- больше не требуется нулевая проверка. - person Ed S.; 07.10.2009
comment
Кроме того, вы можете опустить фигурные скобки для самых верхних используемых блоков, так что неплохо иметь там несколько. - person Ed S.; 07.10.2009
comment
Ресурсы могут быть многократно указаны в блоках using, что может устранить необходимость в глубоком вложении. См. levelofindirection.com/journal/2009 / 9/24 / - person Robert Harvey; 08.10.2009
comment
@Ed Swangren: фиктивный делегат плохо сказывается на производительности и экономит незначительное количество набора текста. Лучше сделать нулевую проверку. - person P Daddy; 09.10.2009
comment
@Ed Swangren: Вызов через делегата намного дороже, чем проверка if, и если кто-то подключается к нему, он становится многоадресным делегатом, что намного дороже, чем вызов через одноадресный делегат. См. Комментарии в ответ на это сообщение: stackoverflow.com / questions / 9033 / hidden-features-of-c / 9282 # 9282 - person P Daddy; 09.10.2009

Непонимание того, что bool - это реальный тип, а не просто соглашение

if (myBooleanVariable == true)
{
    ...
}

или, что еще лучше

if (myBooleanVariable != false)
{
    ...
}

Подобные конструкции часто используются C и C++ разработчиками, где идея логического значения была просто условием (0 == ложь, все остальное верно); в C # или других языках с настоящими логическими значениями это не обязательно (или нежелательно).

Обновлено: последний абзац перефразирован для большей ясности.

person Community    schedule 07.10.2009
comment
В C и C ++ (я еще не слышал о языке C / C ++) это не соглашение и на самом деле неверно. Поскольку все остальное верно, выполнение if(a == true) для некоторого определения истины (скажем, 1) не будет работать должным образом, если a, скажем, 4. Точно так же в обоих случаях if(myBooleanVar) и if(!myBooleanVar) были бы лучшей заменой. - person Tordek; 07.10.2009
comment
Замечательный комментарий - полезно вдаваться в подробности. Мне любопытно, основываясь на ваших комментариях, почему разработчики C ++, которые переходят на C #, настаивают на том, чтобы всегда писать сравнения с истинным и ложным? (Я работал с несколькими, и все они настаивали на этой практике, ссылаясь на C ++ в качестве причины). - person Bevan; 07.10.2009
comment
if (myBool == true) может иметь смысл, если myBool является логическим значением, допускающим значение NULL. - person Rauhotz; 08.10.2009
comment
Это действительно антипаттерн или просто раздражающая избыточность? - person Jeff Sternal; 08.10.2009
comment
@JeffSternal - я думаю, что это антипаттерн, потому что (по крайней мере, в тех случаях, которые я видел) он отражает реальное отсутствие понимания системы типов C #. - person Bevan; 08.10.2009
comment
В Java Boolean a = null; boolean b = a == true; NPE, IIRC. C # отличается? - person Tom Hawtin - tackline; 08.10.2009
comment
Да, C # отличается, потому что существует только один тип: Boolean, определенный во фреймворке. В C # есть bool, но это чисто псевдоним для того же самого. Упаковка - процесс упаковки типа значения для хранения его в куче - влияет только на производительность, а не на что-либо еще. Nullable-bool - это снова другой тип, см. msdn.microsoft.com/en -us / library / b3h38hb0.aspx для получения дополнительной информации. - person Bevan; 08.10.2009
comment
На C и C ++ (я еще не слышал о языке C / C ++). и - это то, что означает в предложении символ /. Знаете ли вы определение, отличное от dictionary.reference.com/help/faq /language/g61.html#Slash? - person Greg; 08.10.2009

Открытые переменные в классах (вместо этого используйте свойство).

Если класс не является простым объектом передачи данных.

См. комментарии ниже для обсуждения и пояснений.

person Community    schedule 07.10.2009
comment
Если приведенное выше не должно вызвать предупреждающий звонок - может быть, это не так четко? - person d91-jal; 07.10.2009
comment
Больно ли для простых DTO использовать свойства вместо общедоступных переменных? Я бы сказал, что нет, поскольку существуют автоматические свойства. Но поскольку я узнал, что привязки данных WPF не работают с общедоступными полями (в отличие от общедоступных свойств), я снова забыл об объявлении общедоступных полей / переменных без средств доступа. - person Simon D.; 08.10.2009
comment
Просто используйте свойства. JITer попытается встроить их, чтобы вы сделали их такими же, как поле, вместо вызовов методов. - person Matthew Whited; 08.10.2009
comment
Условие, которое я бы поставил на if, - это если класс не имеет и никогда не будет иметь никаких инвариантов, которые он должен обеспечить. - person peterchen; 08.10.2009
comment
Автоматические свойства делают Unless бессмысленным. Свойства должны использоваться для любого публичного доступа к переменным. - person Darien Ford; 08.10.2009
comment
Я согласен с использованием автоматических свойств исключительно для тех проектов C #, которые его поддерживают. - person Robert Harvey; 08.10.2009
comment
Я работаю с относительно старым кодом VB, который не имеет автоматических свойств, но все, с кем я работаю, настаивают на объявлении 10 полей частными и 10 свойств получателя / установщика без каких-либо свойств, имеющих настраиваемую обработку. - person Josh Smeaton; 09.10.2009
comment
@Matthew Whited - Нет, свойства структуры НИКОГДА не встраиваются (фактически, любой метод, принимающий или возвращающий структуру, никогда не встраивается (если структура не является параметром ref или out)). Встраиваются только свойства ссылки и примитивного типа. Кроме того, это может отличаться в зависимости от структуры (например, компактная, микро, моно и т. Д.). - person Robert Fraser; 25.05.2010
comment
@ Роберт Фрейзер: .Net 3.5+ Inlining of value types (C# structs). (X86) blogs.msdn.com/b/vancem/archive/2008/05/12/ - person Matthew Whited; 25.05.2010
comment
@Matthew Whited - Моя плохая; не знал, что они исправили это! Ошибка все еще открыта в Connect. Это потрясающе; Теперь я могу гораздо меньше бояться структур. - person Robert Fraser; 27.05.2010

Я действительно видел это.

bool isAvailable = CheckIfAvailable();
if (isAvailable.Equals(true))
{ 
   //Do Something
}

превосходит isAvailable == true анти-паттерн!
Делаем это супер-анти-паттерном!

person Community    schedule 09.10.2009
comment
Вау! Просто вау! Я видел string.Equals, которые раньше использовались для строк вместо ==, но это было намного понятнее - этот парень не знал, что оператор == был перегружен. Но то, что вы показали, занимает первое место! - person Phil; 23.12.2009

Частные автоматически реализованные свойства:

private Boolean MenuExtended { get; set; }
person Community    schedule 07.10.2009
comment
Что-то не так, кроме того факта, что вы вводите вызов метода туда, где он вряд ли понадобится? - person Matthew Scharley; 07.10.2009
comment
@matthew: Я не могу придумать ни одной причины / случая, когда поле было бы не лучше. - person leppie; 07.10.2009
comment
Автоматически реализованное свойство может быть позже преобразовано в полноценное свойство с помощью специальных методов получения и установки. Вы не можете легко сделать это с полем. - person Gart; 07.10.2009
comment
Вы можете, но не двоично-совместимым способом ... но, опять же, они в любом случае являются частными, поэтому они будут двоичными, поскольку поле / свойство не отображается. - person Matthew Scharley; 07.10.2009
comment
Я не вижу в этом проблемы и думаю, что это может быть стоящим дизайнерским выбором. Хотя, конечно, злоупотреблять можно. - person Wedge; 07.10.2009
comment
Во-первых, некоторые элементы управления отражают только свойства, а не поля. Например, PropertyGrid. Иногда вам нужно использовать свойства при работе с отражением, даже если эти свойства являются частными. - person rein; 07.10.2009
comment
@leppie: Это требует некоторого рефакторинга кода и может быть проблемой, если это поле используется во многих местах. Автоматический рефакторинг Visual Studio помогает здесь, но не во всех случаях. - person Gart; 07.10.2009
comment
Как сказал Мэтью выше, у вас должны быть свойства placeholder / empty auto для двоичной совместимости. У частной собственности нет будущих требований к двоичной совместимости. - person vanja.; 07.10.2009
comment
Это не правильно. Связывание данных работает только со свойствами (но не с полями). - person Ed S.; 07.10.2009
comment
@ed: Удачи в привязке к частной собственности! - person leppie; 07.10.2009
comment
Двоичная совместимость и привязка данных - это причины, по которым вам может потребоваться использовать общедоступные свойства, но здесь они не применяются. У свойств есть несколько преимуществ. Вы можете поставить точку останова отладки на доступ. Вы можете легко изменить их уровень доступа для чтения / записи. И они часто могут быть полезны при рефакторинге, например, для переноса нулевых проверок в паре со значениями по умолчанию в само свойство. Учитывая небольшую разницу в усилиях, необходимых для создания автоматически реализуемых свойств, я бы сказал, что вопрос о том, являются ли свойства или поля лучшим значением по умолчанию. - person Wedge; 07.10.2009
comment
Лично я предпочитаю использовать частные свойства по умолчанию, чем выяснять каждый раз, когда я создаю поле, хочу ли я когда-нибудь, чтобы оно было видимым для отражения. Рационализация для создания их полей (устранение ненужных вызовов методов получения / установки) для меня пахнет преждевременной оптимизацией. - person Robert Rossney; 07.10.2009
comment
@Роберт; почему поле не может быть видно через отражение? - person leppie; 07.10.2009
comment
Я полагаю, что для этого могут быть какие-то трудно найти оправдания, но я бы сказал, что это проходит лакмусовую бумажку как антипаттерн. - person Greg; 08.10.2009
comment
Я очень хотел бы знать, о чем говорю. - person Robert Rossney; 08.10.2009

Объявление и инициализация всех локальных переменных в начале каждого метода - это ужасно!

void Foo()
{
    string message;
    int i, j, x, y;
    DateTime date;

    // Code
}
person Community    schedule 07.10.2009
comment
Так меня учили программировать в колледже;) Но больше не делай этого, это больно. - person Ed James; 08.10.2009
comment
Это имело смысл еще до IDE. - person Dean J; 08.10.2009
comment
Разве это не больше субъективное мнение, чем антипаттерн C #? - person Patrik Svensson; 08.10.2009
comment
Что в этом плохого? Если вы правильно кодируете свои методы, они в любом случае достаточно короткие, чтобы увидеть все ваши переменные. Я бы сказал, что переменные должны быть определены в верхней части своего блока, а не метода, если только они не должны быть связаны с проблемами области действия. - person snicker; 09.10.2009
comment
Я согласен с этим - даже если вы сохраняете свои функции довольно маленькими, если переменная используется только для нескольких строк, вы часто можете сразу увидеть тип, и вашим глазам не придется искать до вершины функции. Инициализация наверху для меня показывает либо отсутствие опыта, либо чрезмерное нежелание отказываться от старых привычек. - person Phil; 23.12.2009
comment
На мой взгляд, это в основном вытекает из программирования на C, потому что вам нужно объявить все переменные перед любым вызовом функции. - person K Singh; 22.01.2010
comment
где еще вы должны определить, это требует от вас заранее подумать о методе ur. - person DarthVader; 25.08.2011

Двухстрочный анти-шаблон
Анти-шаблон № 1
Проверка строк на ноль или пустоту

//Bad
if( myString == null || myString == "" )
OR
if( myString == null || myString.Length == 0 )

//Good
string.IsNullOrEmpty(myString)

Anti-Pattern # 2 (только для .NET 4.0)
Проверка строк на наличие нуля, пустого или пробела

//Bad
if( myString == null || myString == "" || myString.Trim() == "")

//Good
string.IsNullOrWhiteSpace(myString) 
person Community    schedule 03.06.2010

Излишнее преобразование (доверьтесь компилятору):

foreach (UserControl view in workspace.SmartParts)
{
  UserControl userControl = (UserControl)view;
  views.Add(userControl);
}
person Community    schedule 07.10.2009
comment
Что за хрень там творится? Вы получаете UserControl, назначаете ему новую ссылку с ненужным приведением, а затем добавляете ее к себе? Почему? - person Ed S.; 07.10.2009
comment
@ed: Хотел бы я знать почему, но некоторое время назад обнаружил, что в нашей кодовой базе таится :) - person leppie; 07.10.2009
comment
@ed: он не добавляется к самому себе. views! = view. ;) - person exhuma; 08.10.2009
comment
Думаю, Решарпер увидит, что вы там сделали. - person comichael; 12.10.2009

if(data != null)
{
  variable = data;
}
else
{
  variable = new Data();
}

может быть лучше записано как

variable = (data != null) ? data : new Data();

и даже лучше написано как

variable = data ?? new Data();

Последний листинг кода работает в .NET 2.0 и выше.

person Community    schedule 09.10.2009
comment
Эээ ... Я думаю, что ваш первый пример должен быть (data! = Null) или перевернуть часть if / else тернарного блока. - person Chris Shouts; 28.10.2009

Меня всегда улавливала речь с акцентом.

Программисты на C ++:

if (1 == variable) { }

В C # это приведет к ошибке компилятора, если вы наберете if (1 = variable), что позволит вам написать код именно так, как вы это имеете в виду, вместо того, чтобы беспокоиться о том, чтобы выстрелить себе в ногу.

person Community    schedule 07.10.2009
comment
Я бы не стал распространять это на программистов на C ++ ... конечно, те, кто это делает, вероятно, с C или C ++, но большинство программистов думают, что читать это раздражает, и не делают этого. - person GManNickG; 07.10.2009
comment
и все же это безопасный поступок. Если вы сделаете опечатку (= вместо ==), вы получите 1 = variable, и компилятор позвонит вам по этому поводу. - person vanja.; 07.10.2009
comment
int variable = 5; if (1 == variable) { } не выдает ошибок. - person Joren; 07.10.2009
comment
C # делает это соглашение ненужным. Этот код: Int32 x = 5; if (x = 5) {} приводит к ошибке 74: невозможно неявно преобразовать тип int в bool. Изменение = на == работает нормально. - person JeffK; 08.10.2009
comment
За исключением случаев, когда переменная имеет логический тип? - person Tom Hawtin - tackline; 08.10.2009
comment
@Tom Hawtin вау. По крайней мере, это предупреждение. Это не будет работать ни с чем, кроме логических типов, но все же ПОЧЕМУ. Почему во имя богов вы хотите, чтобы оператор присваивания возвращал присвоенное значение. У вас есть эта переменная вещь, в которой теперь должно быть ваше значение ... - person Spence; 08.10.2009
comment
@spence Making = return присвоенное значение позволяет использовать шаблон: while ((line = r.ReadLine ())! = null) {// делаем что-то в строке} - person Esben Skov Pedersen; 09.10.2009
comment
Я вижу это в нашем коде, один разработчик использует это, к большому огорчению менеджера разработки. Вы получите ошибку компиляции, если поставите одно равное, так зачем писать так? - person Paul Talbot; 02.06.2010

Я вижу, что не использую тернарный язык, преобразователи в C # иногда делают

понимаете:

private string foo = string.Empty;
if(someCondition)
  foo = "fapfapfap";
else
  foo = "squishsquishsquish";

вместо:

private string foo  = someCondition ? "fapfapfap" : "squishsquishsquish";
person Community    schedule 08.10.2009
comment
Я был одним из новообращенных и делал это несколько раз - спасибо, что Решарпер спас мою задницу :) +1 - person Andrew; 09.10.2009
comment
Я встречал немало людей, которые категорически возражали против ВСЕГДА использования тернарных условных выражений, говоря, что это делает код нечитаемым. Дураки. - person snicker; 09.10.2009
comment
Я также осторожно отношусь к троичным утверждениям. Иногда я предпочитаю их, иногда нет. Есть ли веская причина (с точки зрения языка) всегда использовать их в C #? - person exhuma; 09.10.2009
comment
@exhuma: Вы не должны всегда использовать что-либо, но ?: можете прояснить смысл кода. Блок if/else не только занимает больше места (заставляя ваши глаза сканировать несколько строк, чтобы определить намерение), но также делает логику принятия решения основным фокусом, тогда как тернарный оператор позволяет назначению (или выбору аргумента) быть основным фокусом . Я нахожу это менее отвлекающим. Лично я использую его только тогда, когда он удобно помещается на одной линии. Исключение: комбинированные тернарные операции, правильно отформатированные на нескольких, иногда могут быть более удобочитаемыми, чем несколько if или даже switch. - person P Daddy; 09.10.2009
comment
Если в каждом из условных операторов есть только одна вещь, то тернарный оператор отлично подходит. Но вызов функций (особенно с несколькими параметрами), объединение строк и т. Д. Ухудшает читаемость. - person DisgruntledGoat; 12.10.2009
comment
Было бы неплохо включить {} скобки после условия, даже если это однострочный код. - person Dariusz Woźniak; 11.08.2010

Доступ к измененным закрытиям

foreach (string list in lists)
{
        Button btn = new Button();
        btn.Click += new EventHandler(delegate { MessageBox.Show(list); });
}

(см. ссылку для объяснения и исправления)

person Community    schedule 08.10.2009

Для объединения произвольного количества строк с использованием объединения строк вместо построителя строк

Примеры

foreach (string anItem in list)
    message = message + anItem;
person Community    schedule 08.10.2009
comment
Или, по крайней мере, используйте здесь String.Join. - person Adam Luter; 08.10.2009
comment
увеличение производительности часто не стоит усилий StringBuilder - person Scott Weinstein; 09.10.2009
comment
Похоже, это работа для string.Concat(). - person P Daddy; 12.10.2009

это считается общим?

public static main(string [] args)
{
  quit = false;
  do
  {
  try
  {
      // application runs here .. 
      quit = true;
  }catch { }
  }while(quit == false);
}

Я не знаю, как это объяснить, но это похоже на то, что кто-то улавливает исключение и повторяет код снова и снова, надеясь, что это сработает позже. Например, если возникает исключение IOException, они просто пытаются снова и снова, пока он не сработает.

person Community    schedule 07.10.2009
comment
Вероятно, это дословный перевод VB6 On Error Resume Next - person Benjol; 07.10.2009
comment
Иногда у этого шаблона есть веские причины, но обычно он указывает на недостаток дизайна. - person Wedge; 07.10.2009
comment
Не совсем, дословный перевод этой «прагмы» (?) Был бы попыткой / уловкой вокруг каждой строки и молчаливым отбрасыванием Exception. - person Matthew Scharley; 07.10.2009
comment
В некоторых случаях, например, при сетевых подключениях, если вы отключились, вам может потребоваться автоматическое переподключение. Это требует перехвата исключений ввода-вывода, а затем повторного запуска цикла. Возможно, ваше интернет-соединение оборвалось, а это значит, что оно будет пытаться снова и снова, пока оно не восстановится. Это чаще встречается в сервисах IMO. - person Erik Funkenbusch; 08.10.2009
comment
Это совершенно верно, если вы хотите бесконечное ожидание вместо явного сообщения об исключении в случае ошибки. - person Daniel Daranas; 08.10.2009
comment
Вот так почти я реализовал систему меню, когда впервые играл с Java в первый год обучения в uni. С тех пор я прошел небольшой путь. - person Josh Smeaton; 09.10.2009

В проекте, над которым я работаю, было пятьдесят классов, все унаследованные от одного и того же класса, который был определен всеми:

public void FormatZipCode(String zipCode) { ... }

Либо поместите его в родительский класс, либо в служебный класс в сторону. Ага.

Думали ли вы о просмотре The Daily WTF?

person Community    schedule 08.10.2009

Чрезвычайно сложные методы Page_Load, которые хотят делать все.

person Community    schedule 07.10.2009
comment
C # загружает страницу? Может ты имел ввиду ASP? - person D3vtr0n; 08.10.2009
comment
protected void Page_Load (отправитель объекта, EventArgs e) {// что-то делать} - person Ralph Lavelle; 08.10.2009
comment
Devtron, C # также является языком ASP.NET, который имеет метод загрузки страницы. - person CRice; 08.10.2009
comment
Да, но это не антипаттерн языка (C #), это антипаттерн ASP.NET ... - person Meta-Knight; 08.10.2009

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

person Community    schedule 08.10.2009
comment
Я не думаю, что разработчики (особенно новички) интуитивно ожидают, что свойства должны работать быстро. Я думаю, они этого ожидают, если им сказали ожидать этого. Может, это только я. - person Greg; 08.10.2009
comment
@ Грег: Я не согласен. Свойство выглядит как доступ к переменной (особенно для новых разработчиков). int a = foo.Metric; выглядит быстро. - person P Daddy; 09.10.2009
comment
Я не согласен, и фреймворк LINQ-TO-SQL тоже не согласен, поскольку он предоставляет всю базу данных через свойства - person Esben Skov Pedersen; 09.10.2009

Нашел это несколько раз в системе, которую я унаследовал ...

if(condition){
  some=code;
}
else
{
  //do nothing
}

и наоборот

if(condition){
  //do nothing
}
else
{
  some=code;
}
person Community    schedule 08.10.2009
comment
Я случайно сделал это, когда хотел вернуться к этому блоку и вставить другое предложение, НО теперь я помечаю его // TODO: чтобы я мог найти этот тег. Я никогда не оставлял это поле пустым намеренно, это похоже на то, что я нахожусь в космосе во время работы. - person IanStallings; 09.10.2009
comment
но я видел, как он прокомментировал, что ничего не требуется, и в то время это заставило меня хихикать :) - person Andrew; 09.10.2009
comment
Это лучшие. Прямо там с пустыми блоками-ловушками. - person IanStallings; 09.10.2009
comment
Это ясно показывает, что автор задумался над случаем, когда выражение оценивается в одно из значений, и активно решил, что делать нечего. Я думаю, что это действительно помогает читабельности, если используется правильно. - person erikkallen; 10.10.2009

У меня было такое раньше:

AnEnum e = AnEnum.Abc;
int i = (int)e;
// lots of code
AnEnum f = (AnEnum)Enum.Parse(i, typeof(AnEnum));
person Community    schedule 03.02.2010

if (state == ((int)RowState.Active).ToString())
else if (state == ((int)RowState.NotActive).ToString())

state - это строковое значение сообщения, которое содержит значение из перечисления RowState.

В конце концов, именно так мы проверяем значение.

person Community    schedule 03.02.2010
comment
Итак, что было бы правильным способом сделать это тогда? Мне это кажется разумным. Но опять же, я не знаю C # Enums ...;) - person exhuma; 04.02.2010
comment
Это правильный путь, но узор здесь определенно антипаттерн :) - person Fitzchak Yitzchaki; 04.02.2010

Основная проблема с .NET, похоже, заключается в том, что есть много разработчиков, пришедших из VB 6.0 или (что еще хуже, на мой взгляд, потому что они ошибочно ДОВЕРЯЮТ, что знают, что делать, в то время как программисты VB 6.0, по крайней мере, достаточно скромны, чтобы захотеть узнать что-то новое) Java / C ++.

Люди, слишком невежественные по отношению к современным парадигмам, люди, облепляющие свой код уродливым P / Invoke в худшем из возможных стилей C ++. :-(

person Community    schedule 02.06.2010
comment
В какой-то степени я согласен. Но проблема не всегда в готовности учиться. Мой случай аналогичен, из-за корпоративного решения мне сейчас нужно писать код на C #. И быстрого пятидневного ускоренного курса должно хватить. Я не верю, что это так. И я уверен, что сначала напишу плохой код. Поэтому я и открыл этот вопрос. Чтобы избежать хотя бы некоторого плохого кода :) - person exhuma; 02.06.2010
comment
exhuma, к сожалению, 5-дневного курса НЕ хватит. По крайней мере, C # не является сложным языком для изучения, но есть несколько вещей, которые вам не следует делать, и есть много передовых методов. Однако я видел полный мусорный код, например, ручное повторение вместо использования foreach (...) и все такое. В основном это потому, что люди пришли из неуклюжего языка, такого как VB, C ++ или Java. Подумайте об этом так: C # - наименее неуклюжий из доступных языков. Если что-то кажется неуклюжим, значит, оно неправильно закодировано. - person stormianrootsolver; 02.06.2010
comment
Это именно то, что я имел в виду ... :) Вы можете сказать это на многих языках. Нужен опыт! - person exhuma; 03.06.2010

Невежество - это блаженство (знайте свои рамки):

TimeSpan keyDays = new TimeSpan(Licence.LicenceExpiryDate.Ticks);
TimeSpan nowDays = new TimeSpan(System.DateTime.Now.Ticks);

int daysLeft = keyDays.Days - nowDays.Days;
person Community    schedule 07.10.2009
comment
Конечно, это довольно многословно и отчасти избыточно. Может быть int daysLeft = DateTime.Now.Subtract (Licence.LicenceExpiryDate) .Days; Но многословие ИМХО не является антипаттерном, производительность и удобочитаемость здесь не должны сильно пострадать. - person Simon D.; 08.10.2009
comment
Глупость - это антипаттерн :) - person leppie; 08.10.2009
comment
@exhuma: вы можете сделать то же самое с: (Licence.LicenceExpiryDate - DateTime.Now) .Days - person leppie; 09.10.2009
comment
Не заглядывая в среду IDE, разве это не должно быть TotalDays leppie? - person Phil; 23.12.2009
comment
Ах, ой - моя плохая. Итак, TotalDays дает дробные дни, а Days просто дает целые дни. - person Phil; 23.12.2009
comment
Хммм, на самом деле, если подумать, это заставляет ваше предложение производить разные значения, Леппи - вычитание одного из другого даст другой временной интервал, чем keyDays.Days - nowDays.Days, поскольку последний дает дельту временного промежутка с начала дня для keyDays.Days и nowDays.Days. Предполагая, что они действительно хотят, вам придется использовать: (License.LicenseExpiryDate.Date - DateTime.Now.Date) - person Phil; 23.12.2009
comment
@ Фил: Я этого даже не заметил. Для этого кода я думаю, что он просто отображал количество дней, оставшихся до лицензии. - person leppie; 23.12.2009

При кодировании свойства просто автоматически назначаем ему геттер и сеттер, не задумываясь о его использовании. Часто get или set не используются, и свойство должно быть доступно только для чтения (получения) или только для записи (установки).

person Community    schedule 10.03.2011

Я видел несколько недавно.

Никогда не заканчивающаяся цепочка параметров

public string CreateJob(string siteNumber, string customer, string jobType, string description, string reference, string externalDoc, string enteredBy, DateTime enteredDateTime)
    {
        //recordtype = 0 for job
        //load assignments and phases set to false
        return Create(0, siteNumber, customer, jobType, description, reference, externalDoc, enteredBy, enteredDateTime, false, false);
    }

public string Create(int recordType, string siteNumber, string customer, string jobType, string description, string reference, string externalDoc, string enteredBy, DateTime enteredDateTime, bool loadAssignments, bool loadPhases)
{
    _vmdh.Fields.FieldByName("WDDOCTYPE").SetValue(recordType, false);
    _vmdh.Fields.FieldByName("NMDOCID").SetValue(-1, false);
    _vmdh.Init();           
        ....
        ...
        // And it keeps going
    }

Интересно, что происходит при закрытии формы?

 private void frmAddImages_FormClosing(object sender, FormClosingEventArgs e)
{
    if (DialogResult != DialogResult.OK)
    {
        if (IsDirty)
        {
            e.Cancel = !(MessageBox.Show("Are you sure that you want to exit without saving", "Form Not Saved", MessageBoxButtons.YesNo) == DialogResult.Yes);
        }
    }
    }

Строчно набранный

switch (cbDateFilter.Text)
            {
                case "This Week":
                    dt = DateTime.Now;
                    while (dt.DayOfWeek != DayOfWeek.Monday) dt = dt.AddDays(-1); //find first day of week
                    dtFrom.Value = DateTime.Parse(dt.ToString("dd/MM/yyyy 00:00:00"));
                    dtTo.Value = DateTime.Parse(dt.AddDays(6).ToString("dd/MM/yyyy 23:59:59"));
                    break;

                case "This Month":
                    dt = DateTime.Now;
                    while (dt.Day != 1) dt = dt.AddDays(-1); // find first day of month
                    dtFrom.Value = DateTime.Parse(dt.ToString("dd/MM/yyyy 00:00:00"));
                    dtTo.Value = DateTime.Parse(dt.AddMonths(1).AddDays(-1).ToString("dd/MM/yyyy 23:59:59"));
                    break;

                case "This Quarter":
                    // if at end of Quarter then we need subtract -4 to get to priv Quarter
                    dt = DateTime.Now;
                    while (dt.Month != 7 &&
                        dt.Month != 10 &&
                        dt.Month != 1 &&
                        dt.Month != 4) dt = dt.AddMonths(-1); //find first month, fiscal year
                    while (dt.Day != 1) dt = dt.AddDays(-1); // find first day on month
                    dtFrom.Value = DateTime.Parse(dt.ToString("dd/MM/yyyy 00:00:00"));
                    dtTo.Value = DateTime.Parse(dt.AddMonths(3).AddDays(-1).ToString("dd/MM/yyyy 23:59:59"));
                    break;
person Community    schedule 04.08.2011

Использование (плохо)

IEnumerable<Bar> foo = ...
if (foo.Count() > 0)
{
    ...
}

вместо (хорошо)

IEnumerable<Bar> foo = ...
if (foo.Any())
{
    ...
}

чтобы проверить, содержит ли что-нибудь IEnumerable. Count() должен пройти через всю коллекцию с помощью MoveNext(), в то время как Any() должен вызвать MoveNext() только один раз.

person Community    schedule 06.09.2011

Чрезмерное использование / злоупотребление инициализаторами объектов для всего, вероятно, из-за лени:

var person = new Person
{
    FirstName = "joe",
    (... lots of setters down here)
};

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

person Community    schedule 07.10.2009
comment
ИМХО, создавать конструкторы со многими параметрами просто для инициализации вашего класса - не лучший вариант. Вы должны предоставить простые конструкторы и дополнительные свойства. Конструкторы (также относящиеся к методам) с более чем 3 параметрами имеют очень неприятный запах. - person Christian Schwarz; 07.10.2009
comment
Излишне доступные для записи (т.е. не для чтения) поля имеют худший запах, ИМО. - person Tordek; 07.10.2009
comment
Я согласен с обоими вашими комментариями, но @Christian: если это обязательные вещи, которые нужно установить для того, чтобы объект был в допустимом состоянии, то IMO вы должны создать ctor, который требует их всех. Конечно, могут быть перегрузки, принимающие меньшее количество параметров, которые инициализируют объект с некоторыми разумными значениями по умолчанию через синтаксис : this(...). И да, если автор приводит более 3 аргументов, я с вами согласен, что начинает пахнуть - person mookid8000; 07.10.2009
comment
Этот код намного читабельнее, чем если бы он был превращен в конструктор. - person Egor Pavlikhin; 08.10.2009
comment
@HeavyWave Я согласен с этим, когда вы имеете дело с DTO, где null является приемлемым значением для любого из свойств классов, но полностью лишает класс возможность гарантировать любое, что он действителен или согласован. - person mookid8000; 10.10.2009
comment
@Christian: Если вы широко используете неизменяемость, вы можете получить конструкторы с 10 параметрами. Неизменность - это запах? Или объект данных с 10 свойствами только для чтения - это запах? Я бы сказал ни то, ни другое. Возможно, дело в том, что нет способа создать свойство, которое можно установить только в блоке конструктора или инициализатора. - person erikkallen; 10.10.2009

person    schedule
comment
@Spence: .Close() не обязательно «старый код». Некоторые классы предоставляют Close() метод в качестве псевдонима для Dispose(), где close имеет больше смысла семантически. - person Matthew Scharley; 07.10.2009
comment
Истинный. Но принудительное использование IDisposable позволяет использовать инструменты статического анализа, чтобы определить, когда типы, реализующие IDisposable, не использовались. Кроме того, все API-интерфейсы, к которым у Microsoft был доступ, реализовали IDisposable, чтобы разрешить использование шаблона using (). По сути, они стандартизировали шаблон, чтобы упростить выявление ошибок. API .Close () обычно являются возвратом к API-интерфейсам, отличным от .Net, к которым обращается этот код. - person Spence; 07.10.2009
comment
Просто чтобы прояснить, чтобы определить, когда объекты IDisposable не были удалены. - person Spence; 07.10.2009
comment
Просто чтобы добавить: установка для Disposed объектов значения null имеет смысл по крайней мере для элементов управления WinForms, чтобы предотвратить утечку памяти: social.msdn.microsoft.com/Forums/en-US/netfxcompact/thread/ - person Michael Stum; 07.10.2009
comment
Тогда ты меня напугал. Это ошибка в компактной платформе .Net, а не в выигрышных формах. Слабая ссылка работает в реальной среде CLR .net, и я также поддерживаю тот факт, что вызов null будет оптимизирован в режиме выпуска (что было одним из основных мотивов для шаблона удаления, который является вызовом метода, заставляющим время жизни объект должен прослужить хотя бы так долго). Но .Net CF определенно интересный зверь. - person Spence; 07.10.2009