10 распространенных ошибок при программировании на C# и как их избежать

в 17:21, , рубрики: .net, C#, менеджмент проектов, Программирование, разработка программного обеспечения

Каждый разработчик совершает ошибки, никто от них не застрахован.

Большинство программистов учатся методом проб и ошибок. Это часть пути от Junior C# Developer до Senior C# Developer. Тем не менее, не обязательно совершать самому все эти ошибки, чтобы пройти этот путь.

Ниже приведены типичные ошибки, с которыми можно встретиться программируя на C#, и пути их обхода.

1. Итерация значений вместо использования LINQ

Очень часто при написании приложения стоит задача считать множество значений и сохранить их как список (List) или другую коллекцию. Сделать это можно, например, простой итерацией.

Рассмотрим создание списка клиентов. Если клиентов сотня тысяч, создать специфический набор данных, перебирая все эти записи — не совсем эффективно. Вместо использования операторов for или foreach можно использовать LINQ (Language-Integrated Query). Данный язык запросов, синтаксис которого напоминает SQL, фирма Microsoft добавила в языки программирования платформы .NET Framework в конце 2007 г. LINQ изначально был спроектирован для того, чтобы облегчить работу с такими объектами как коллекции.

Приведем пример:

Неэффективный способ:

foreach (Customer customer in CustomerList) {
if (customer.State == «FL») {
tax += customer.Balance;
}
}

Эффективный способ:

var customers = (from customer in CustomerList
where customer.State == "FL"
select customer.Balance).Sum();

Одна строчка кода на LINQ сразу возвращает набор данных, состоящий из 1000 клиентов, вместо перебора 100 000 объектов. Работать одновременно с 1000 значений более эффективно, чем перебирать 100 000.

2. Нелогичное использование «var», если известен тип данных

С момента появления ASP.NET MVC многие программисты стали использовать LINQ для работы с коллекциями. В большинстве случаев тип получаемых данных неизвестен. В этом случае оператор «var» помогает избежать ошибок при выполнении кода, в случае, если результатом является NULL или неожиданный тип данных.

Тем не менее, желательно явно декларировать тип данных, если он известен. Это улучшает читаемость кода, и помогает другим программистам работать с ним без лишних усилий.

Рассмотрим предыдущий пример:

var customers = (from customer in CustomerList
where customer.State == "FL"
select customer.Balance).Sum();

В этом примере, возможно, Sum должен иметь тип decimal. Если это точно известно, нужно задекларировать переменную как decimal. Когда другой программист будет читать этот код, он будет знать, что значение будет иметь тип decimal, а не int, например.

3. Использование глобальных переменных класса вместо свойств

Свойства являются обычными для объектно-ориентированных языков программирования. Они предоставляют гибкий механизм для чтения, записи или вычисления значения частного поля. Но зачем их использовать, если любые переменные класса можно объявить глобальными? Ответ один — свойства дают возможность контролировать как они будут использоваться, чего нельзя отнести к глобальным переменным.

Рассмотрим следующий код:

public decimal Total {get; protected set;}

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

4. Забыть освободить объект

Нехватка памяти и других ресурсов компьютера — реальная проблема для различных приложений. C# предоставляет довольно удобный путь использовать метод Dispose, когда работа с объектом закончена. Для этого даже не обязательно этот метод указывать явно. Об этом позаботиться оператор «using».

Рассмотрим:

file.Read(buffer, 0, 100);

Вышеописанный код, если явно не указать закрытие объекта, может стать причиной нехватки оперативной памяти. Это легко предотвратить используя оператор «using».

using (FileStream file = File.OpenRead("numbers.txt")) {
file.Read(buffer, 0, 100);
}

Теперь приложение считает информацию из файла и закроет объект по окончании.

5. Использование «» вместо string.Empty

Это всего лишь небольшая досада для программиста, она больше влияет на читаемость кода, нежели на его эффективность. Например, «» может быть ошибочно понят как символ пробела « », а это уже совершенно другое значение. Используя string.Empty вместо «» для инициализации строковой переменной, можно избежать любую ошибочную двусмысленность.

6. Использование общих исключений Try – Catch

Многие начинающие программисты используют общий класс Exception вместо того, чтобы явно указывать тип перехваченного исключения. Конечно, все существующие в C# классы исключений являются производными от общего класса Exception и можно создать собственный класс исключений, который будет наследовать общий класс. Но в любом случае предпочтительно использование конкретных исключений вместо общих.

Неэффективный способ:

try {
newInteger = int.Parse(astring);
} catch (Exception e) {
// do something here
}

Эффективный способ:

try {
newInteger = int.Parse(astring);
} catch (FormatException) {
// do something here
}

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

7. Использование методов внутри блока Try – Catch

Ме́тоды являются основой объектно-ориентированного программирования. Выше был приведен пример простого блока Try — Catch, который содержит только один оператор с обработчиком исключения.

Обычная ошибка, которую совершают разработчики, — окружить метод блоком исключения Try – Catch .

Блоки Try – Catch лучше располагать в логической секции кода.
Правильно закодированный метод, должен сам выбрасывать исключение, чтобы передать его на верхний уровень для обработки.

Кроме того, не нужно использовать только один блок, если метод совершает несколько логически разных процедур, например, читает файл, распределяет его содержимое по переменным и затем записывает результат в базу данных. Разбейте блоки так, чтобы были видны: чтение файла, занесение данных, сохранение информации в базу данных.

8. Некорректное соединение строковых переменных

В старых версиях языка для соединения двух строковых переменных достаточно было использовать знак «+». Однако реализация данного пути не всегда была эффективной и Microsoft представил класс StringBuilder, созданный для оптимизации скорости и памяти при работе со строковыми величинами.

Используйте StringBuilder всякий раз, когда нужно соединить строки и для других операций над строковыми переменными. Конечно, для работы с совсем простыми строчками это делать не совсем обязательно, но для обработки данных полученных из файла или базы данных класс StringBuilder незаменим.

9. Не забудьте про журнал ошибок

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

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

10. Наконец, не забудьте обновить свой код

Это ошибка не только программистов на C#, но на других языках.

Visual Studio объединена с Team Foundation Server (TFS). Это хорошая среда для команды разработчиков, но это не будет правильно работать, если программист забудет скачать утром обновленный код, перед тем как продолжить свою работу.

Несомненно, можно объединить 2 различных версии кода потом, но это не всегда делается корректно и может привести к неожиданным ошибкам.

Не нужно забывать скачивать последнюю версию кода перед началом работы и загружать на сервер ваши последние наработки в конце. Никогда не загружайте код с ошибками в нем. Только тот, который может быть скомпилирован. TFS имеет систему, позволяющую компилировать код «на лету». Безошибочное компилирование позволяет быть уверенным, что другие программисты могут скачать этот код и использовать его.

Заключение

C# — достаточно сложный язык. Когда начинаешь изучать объектно-ориентированное программирование, сталкиваешься с большим количеством трудностей. Здесь так много различных правил и стандартов, что непросто избежать ошибок. Однако, делая выводы из своих и чужих ошибок, можно стать хорошим программистом, который создает эффективные и продуктивные приложения.

Автор: ingertum

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js