PDA

Просмотр полной версии : [Информация] Подсказки по улучшению C# кода. Часть 1


Sinyss
09.07.2013, 03:06
1. А вы используете механизм исключений для проверки ввода пользователя?
Если да, то вы замедляете выполнение примерно в 56 раз.
Например, вы проверяете данные что ввел пользователь и если что то не так - выбрасываете исключение:
public void Check()
{
try
{
//код проверки

}
catch (Exception ex)
{
throw new Exception("Что то не так");
}

}
Теперь покажем что так делать не стоит:
class Program
{
public static void ThrowTest()
{
throw new Exception("This is exceptopn");
}
public static Boolean Return()
{
return false;
}

static void Main(string[] args)
{

Stopwatch sw = new Stopwatch();
sw.Start();

try
{
ThrowTest();
}
catch
{

}
sw.Stop();
Console.WriteLine("С исключением " + sw.ElapsedTicks);
long n = sw.ElapsedTicks;
sw.Restart();
try
{
Return();
}
catch
{

}
sw.Stop();
Console.WriteLine("С Return " + sw.ElapsedTicks);
long m = sw.ElapsedTicks;
Console.WriteLine(n+"/"+m+"="+n/m);
Console.ReadLine();
}
}
Результат:
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Доказательство довольно просто. В одной функции я выкидываю Exception во второй возвращаю булевское значение после проверки ввода. На скрине время выполнения в тиках 1й и 2й функции.
Вывод:
"Не вызывайте исключения для проверки данных вводимых пользователем. Используйте булевские значения для этого." Потому что объекты исключения обходятся довольно дорого.


2. Не используйте try-catch внутри цикла, если этого можно избежать.
Код проверки:

class Program
{
static void Method1()
{
for (int i = 0; i < 1000; i++)
{
try
{
int value = i * 100;
if (value == -1)
{
throw new Exception();
}
}
catch
{
}
}
}

static void Method2()
{
try
{
for (int i = 0; i < 1000; i++)
{
int value = i * 100;
if (value == -1)
{
throw new Exception();
}
}
}
catch
{
}
}

static void Main(string[] args)
{

Stopwatch sw = new Stopwatch();
sw.Start();
Method1();
sw.Stop();

Console.WriteLine("Внутри " + sw.ElapsedTicks);

sw.Restart();
Method2();
sw.Stop();
Console.WriteLine("Снаружи " + sw.ElapsedTicks);
Console.ReadLine();
}
}
Результат:
[Ссылки могут видеть только зарегистрированные и активированные пользователи]

3. Вы достаточно безумны что бы использовать оператор new для типа int?
Часто можно встретить ошибку "Unassigned local variable" или если перевести: "Не объявленная локальная переменная"

class Program
{
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000; i++)
{
int a = new int();
a = 100;
}
sw.Stop();
Console.WriteLine("Используя оператор new:- " + sw.ElapsedTicks);
sw.Restart();
for (int i = 0; i < 1000; i++)
{
int a = 0; // поскольку после a = new int() а становится равным 0, по и тут объявим что она равна 0.
a = 100;
}
sw.Stop();
Console.WriteLine("Без оператора new:- " + sw.ElapsedTicks);
Console.ReadLine();
}
}

Результат:
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
В 2.333(3) раз больше...

4. Функция это хорошо, но не всегда
Вообще хорошим тоном считается разбивать код на функции и да, это действительно хорошо для некоторых заданий. Есть тысячи преимуществ у функций, но они же могут снизить производительность приложений. Я не говорю что функции это плохо, но их вызов дорогостоящая операция.
Пример:
class test
{
public static void Print()
{
Console.WriteLine("Я - функция из класса");
}
}


class Program
{
public static void Print()
{
Console.WriteLine("Я - функция из класса");
}
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start();
test.Print();
sw.Stop();
Console.WriteLine(sw.ElapsedTicks);

sw.Restart();
Console.WriteLine("Я - просто из фунции main");
sw.Stop();
Console.WriteLine(sw.ElapsedTicks);

Console.ReadLine();
}
}
Результат:
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Хм, примерно в 20 раз дольше....

5. Выбирайте, когда использовать класс, а когда - структуру.
Допустим что все понимают между ними разницу, я не буду здесь описывать различия, это может занять отдельный топик. ( Внимательному читателю вопрос: Стоит ли в следующей теме описать разницу и примеры применения? )

На самом деле единицы из знакомых мне разработчиков используют структуры, но они явно никогда не проводили замеры производительности.
Давайте проведем тест:
struct MyStructure
{
public string Name;
public string Surname;
}
class MyClass
{
public string Name;
public string Surname;
}
class Program
{
static void Main(string[] args)
{
// объявим новую структуру и класс
MyStructure[] objStruct = new MyStructure[1000];
MyClass[] objClass = new MyClass[1000];


Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000; i++)
{
objStruct[i] = new MyStructure(); // Создадим новую структуру и заполним ее. И так 1000 раз.
objStruct[i].Name = "Алекс";
objStruct[i].Surname = "Фамилия";
}
sw.Stop();
Console.WriteLine("Для структуры:- " + sw.ElapsedTicks);
sw.Restart();

for (int i = 0; i < 1000; i++)
{
objClass[i] = new MyClass(); // Создадим новый класс и заполним его. И так 1000 раз.
objClass[i].Name = "Алекс";
objClass[i].Surname = "Фамилия";
}
sw.Stop();
Console.WriteLine("Для класса:- " + sw.ElapsedTicks);

Console.ReadLine();
}
}
Результат:
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Время создания объектов класса немножко больше чем в 16 раз больше чем для структуры... Более чем очевидно что структуры намного быстрее чем класс. И опять же программа была скомпилирована в режиме Release с включенными оптимизациями.

PS: Все исходники были скомпилированы в режиме "Release" с включенными оптимизациями. Возможно небольшое различие между результатами отображенными на скринах и теми что получите вы, поскольку на время выполнения влияет также загруженность процессора, оперативки и тд. По возможности я старался выбирать средние результаты, были и хуже...