Тази статия е огледална статия за машинен превод, моля, кликнете тук, за да преминете към оригиналната статия.

Изглед: 20516|Отговор: 0

[Бакшиши] Четиридесет и седем начина за оптимизиране на C# програма

[Копирай линк]
Публикувано в 15.03.2018 г. 10:41:59 ч. | | |

1. Заменете достъпните полета с атрибути

1、. .NET обвързването на данни поддържа само свързване на данни, а можете да получите ползите от свързването на данни, използвайки атрибути.
2. В опцията get and set access към свойството можете да използвате lock, за да добавите поддръжка за многонишковост.

2. Readonly (константа на изпълнение) и Const (константа на компилиране)

1. Const може да се използва само за примитивни типове, enums и низове, докато readonly може да бъде всеки тип;
2. CONST ще бъде заменен със специфична константа при компилиране, така че ако се използват както Const, така и Readonly стойности в референтния текст, промяната към readonly ще промени първоначалната цел на дизайна, а именно необходимостта от прекомпилиране на променената асемблер, за да се препрати новата константна стойност.
3. Const е по-ефективен от readonly режима, но губи гъвкавостта на приложението.

3. IS и AS

1. И двете са преобразувания на типове по време на изпълнение, тъй като операторите могат да се използват само в референтни типове, докато is може да използва стойности и референтни типове;
2. Обичайната практика е да се използва IS за определяне на типа, а след това селективно да се използва оператор за преобразуване на тип as или силен (конверсия, дефинирана от оператор).

4. ConditionalAttribute вместо #if #endif条件编译

1. ConditionalAttribute се използва само на ниво метод, а други елементи като типове, атрибути и др. са невалидни. И #if #endif则不受此限制;
2. ConditionalAttribute може да добавя множество операции OR (OR) за условия на компилация, а #if #endif则可以添加与(AND) [тук може да бъде напълно дефиниран като друг отделен символ];
3. Дефиницията ConditioanlAttribute може да бъде поставена в отделен метод, за да направи програмата по-гъвкава.

5. Осигурете метода ToString()

1. Може да предоставя подробна информация на потребителите по по-приятелски начин;
2. Използвайте метода IFormatter.ToString() за по-гъвкава персонализация, и ако добавите интерфейсите IFormatProvider и ICustomFormatter, ще има повече смисъл да персонализирате изхода на съобщението.

6. Разликата между стойност и референтен тип

1. Типовете стойности не поддържат полиморфизъм, който е подходящ за съхранение на данни, управлявани от приложения, докато референцията поддържа полиморфизъм, който е подходящ за дефиниране на поведението на приложенията.
2. За масиви, дефинирани като типове стойности, производителността на програмата може значително да се подобри;
3. Типът стойност има по-малко фрагментация на купчината памет, отпадъци от паметта и индиректен достъп до тях, а връщането му в метода се извършва под формата на репликация, за да се избегне излагането на вътрешната структура на външния свят.
4. Типовете стойности се използват в следните сценарии: Отговорностите на типовете се използват основно за съхранение на данни; Публичните интерфейси са напълно дефинирани от някои атрибути за достъп на членове на данните; Никога няма подкласове; Никога няма полиморфно поведение.

7. Типовете стойности трябва да се реализират възможно най-константни и атомарни типове

1. Да направим кода си по-лесен за писане и поддръжка;
2. Три стратегии за инициализация на константи: в конструкцията; растителен метод; Конструирайте променлив помощен клас (например StringBuilder).

8. Уверете се, че 0 заслужава валиден статус

1. Стандартното състояние на типа стойност трябва да е 0;
2. 0 от типа enum не трябва да е невалиден; В атрибута FlagsAttribute е да се гарантира, че стойността 0 е валидно състояние;
3. Когато низът е празен, може да се върне низ. празен низ за празен.

9. Множество представителни отношения с равна преценка

1. ReferenceEquals() определя, че препратките са равни, и трябва да е вярно, когато и двете се отнасят до един и същ обект.
2. Статичният метод Equals() се използва първо за преценка по референция, а след това за оценка на типа стойност;
3. За преценката на типа референция можете да използвате метода на пренаписване Equals() при използване на стойностна семантика.
4. При пренаписване на метода Equals(), методът GetHashCode() също трябва да бъде пренаписан, а операцията operater==() трябва да се предоставя едновременно.

10. Разберете недостатъците на метода GetHashCode()

1. GetHashCode() се прилага само към хеш стойности на ключове, дефинирани с ** хеш, като HashTable или Dictionary;
2. GetHashCode() трябва да следва съответните три правила: два равни обекта трябва да връщат един и същ хеш код; трябва да е инвариант на инстанция; Хеш функцията трябва да произведе случайно разпределение между всички цели числа.

11. Дайте приоритет на използването на foreach loop оператори

1. foreach може да елиминира проверката на компилатора на границата на масива на for цикъла;
2. Кръговата променлива на foreach е само за четене и има явна трансформация, която създава изключение, когато типът на обекта на обекта ** е неправилен;
3. **, необходим за използване на foreach, е: да има публичен метод GetEnumberator(); Интерфейсът IEnumerable е изрично реализиран. Интерфейсът на IEnumerator е реализиран;
4. foreach може да донесе ползите от управлението на ресурси, защото ако компилаторът може да определи интерфейса с IDisposable, може да използва оптимизирания try... накрая блокирайки;

12. Инициализацията на стандартното поле е по-добра от оператора за присвояване

1. Животът на полето ще инициализира типа стойност на 0, а референтния тип на null по подразбиране.
2. Инициализацията на един и същ обект многократно намалява ефективността на изпълнение на кода.
3. Поставянето на инициализацията на полето в конструктора е благоприятно за обработка на изключения.

13. Използвайте статичния конструктор за инициализация на статични елементи

1. Статичният конструктор ще бъде изпълнен преди да бъде достъпен какъвто и да е метод, променлива или атрибут на клас;
2. Статичните полета също ще се изпълняват преди статичния конструктор, а статичният конструктор е благоприятен за обработка на изключения.

14. Използвайте веригата на конструкторите (в. NET 4.0 вече решава този проблем с опционални параметри)

1. Използвайте това, за да предадете работата по инициализация на друг конструктор и използвайте база, за да извикнете конструктора на базовия клас;
2. Последователността от операции на типови екземпляри е: задайте всички статични полета на 0; Изпълнение на статични инициализатори на полето; статичен конструктор, който изпълнява базовия клас; Статични конструктори, които изпълняват текущия тип;
Задайте всички полета на instance на 0; Изпълнение на инициализатори на полета на екземпляра; Изпълнете съответния конструктор на базов клас; Изпълнете конструктора на instance от текущия тип.

15. Използвайте използване и try/finally оператори за почистване на ресурсите

В метода Dispose() на IDisposable интерфейса GC.SuppressFinalize() може да се използва, за да уведоми събирача на отпадъци, че крайната операция вече не се извършва.

16. Минимизиране на отпадъците в паметта

1. Отнема допълнително време на процесора, за да се разпределят и унищожат обекти на купчина;
2. Техники за намаляване на броя на присвоените обекти: често използвани локални променливи се повишават в полета; Предоставя клас, който съхранява често срещани инстанции на Singleton обекти, изразяващи специфични типове.
3. Използвайте StringBuilder за изпълнение на сложни операции със низове.

17. Минимизирайте опаковането и разопаковането

1. Обърнете внимание на имплицитното преобразуване на даден тип в System.Object и този тип стойност не трябва да се заменя с System.Object тип;
2. Използването на интерфейси вместо типове може да избегне "boxing", тоест имплементиране на стойностни типове от интерфейси и след това извикване на членове през интерфейси.

18. Прилагане на стандартния режим Dispose

1. За да използва ресурси извън паметта, трябва да има финализатор, колекторът на боклука ще добави реализираните финализаторни обекти в опашката за прекратяване след завършване на обектите памет, които не са ги прекратили, а след това събирачът на боклук ще стартира нова нишка, за да стартира финализаторите върху тези обекти. Това може да избегне проблема с изтичане на памет, причинено от неосвобождаване на неуправлявани ресурси на паметта.
2. Използването на метода IDisposable.Dispose() изисква четири аспекта на работата: освобождаване на всички неуправлявани ресурси; Освободи всички управлявани ресурси; Задайте статус маркер, който да показва дали Dispose() е изпълнен; Извикай GC.SuppressFinalize(this), за да отмени операцията за прекратяване на обекта;
3. Добавете защитен виртуален метод Dispose() към типа, който се нуждае от полиморфизъм, и производният клас освобождава задачата си чрез пренаписване на този метод.
4. В типа, който изисква интерфейс с IDisoposable, трябва да реализираме терминатор, дори и да не ни е нужен.

19. Дефинирайте и реализирайте интерфейси върху типове наследяване

1. Несвързани типове могат съвместно да реализират общ интерфейс и е по-лесно да се реализира интерфейс, отколкото наследяване;
2. Интерфейсът е относително стабилен, той капсулира набор от функции в интерфейса като други видове договори за имплементация, докато базовият клас може да се разширява с течение на времето.

20. Разграничаване между реализация на интерфейс и виртуално пренаписване на метод

1. При реализиране на интерфейс в базовия клас, производният клас трябва да използва нов, за да скрие използването на базовия клас метод;
2. Методът на интерфейса на базовия клас може да бъде деклариран като виртуален метод и след това реализиран в производния клас.

21. Използвайте възлагането за изразяване на обратни позиви

1. Самият делегат не осигурява никакво улавяне на изключения, така че всяко многокаст повикване на делегат ще прекрати цялата верига на повиквания.
2. Чрез показване и извикване на всяка целева делегация във веригата от делегати, можете да избегнете мултикаст делегатите, които връщат само изхода на последния делегат.

22. Използване на събития за дефиниране на външни интерфейси

1. Трябва да бъде декларирано като често събитие и да остави компилатора да създава методи за добавяне и премахване за нас.
2. Използвайте контейнера System.ComponentModel.EventHandlelerList за съхранение на всеки обработвач на събития и го използвайте за скриване на сложността на всички събития, когато типът съдържа голям брой събития.

23. Избягвайте връщане на препратки към вътрешни класови обекти

1. Тъй като достъпът до обект тип стойност създава копие на обекта, атрибутите на дефиниране на тип стойност няма да променят състоянието вътре в типовия обект;
2. Константните типове могат да избегнат промяната на състоянието на обекта;
3. Дефинирайте интерфейса, който ограничава достъпа до подмножество и минимизира увреждането върху вътрешното състояние на обекта.
4. Дефинирайте обвивка, който ограничава достъпа до друг обект;
5. Когато клиентският код промени вътрешните елементи на данните, може да се реализира режимът Observer, така че обектът да може да проверява или съответства на промените.

24. Декларативното програмиране е по-добро от императивното програмиране

Възможността за грешки в множество подобни ръкописни алгоритми може да се избегне и се предоставя ясен и четим код.

25. Имплементирайте типове възможно най-сериализирани

1. Типът не представлява UI контрол, прозорец или форма, и типът трябва да поддържа сериализация;
2. При добавяне на десериализирания атрибут NonSerializedAttribute, стойността по подразбиране може да бъде заредена чрез метода OnDeserialization(), който реализира IDeserializationCallback;
3. В контрола на версиите можете да използвате интерфейса ISerializable за гъвкав контрол и да предоставите конструктор за сериализация за инициализация на обекти според данните в потока, както и да изисквате разрешение за изключенията SerializationFormatter при имплементиране.
4. Ако трябва да създадете производен клас, трябва да предоставите метод с кука за производния клас.

26. Използвайте IComparable и IComparer интерфейси за реализиране на сортиращи връзки

1. IComparable интерфейсът се използва за реализиране на най-естествената сортираща връзка за типове, претоварване на четири оператора за сравнение и предоставяне на претоварена версия на метода CompareTo() за приемане на специфични типове като параметри.
2. IComparer се използва за предоставяне на сортиращи връзки, различни от IComparable, или за предоставяне на сортиращи връзки, които самият тип твърди, че не са реализирани.

27. Избягвайте ICloneable интерфейси

1. За типове стойности няма нужда от поддръжка на ICloneable интерфейс, просто използвайте операцията по подразбиране;
2. За базови класове, които може да се нуждаят от поддръжка на ICloneable интерфейси, трябва да се създаде защитен конструктор за репликация за тях и да се избягват IConeable интерфейси.

28. Избягване на оператори за принудително преобразуване

Използването на конструктори вместо оператори за конверсия може да направи работата на конверсията по-ясна, което лесно може да доведе до странни бъгове поради временни обекти, използвани след конверсията.

29. Използвайте новия модификатор само когато натрупването на нови версии създава проблеми

30. Имплементирайте CLS-съвместими асембли колкото е възможно повече
1. За да се създаде съвместима асемблея, трябва да се спазват две правила: параметрите и типовете стойности за връщане, използвани от всички публични и защитени членове на събранието, трябва да са съвместими с CLS; Всеки публичен и защитен член, който не е съвместим с CLS, трябва да има съвместима с CLS алтернатива;
2. Можете да заобиколите проверката за тип съвместимост с CLS, като изрично имплементирате интерфейса, и CLSCompliantAttribute няма да провери съвместимостта на частните членове с CLS.

31. Прилагайте кратък и сбит метод колкото е възможно повече

1. JIT компилаторът компилира в единици методи, а методите, които не са извикани, няма да бъдат компилирани от JIT;
2. Ако кодът на Case оператора в по-дългия Switch бъде заменен с един метод наведнъж, спестяното от JIT компилатора времето ще се умножи;
3. Кратки и кратки методи и изборът на по-малко локални променливи могат да постигнат оптимизирана употреба на регистри;
4. Колкото по-малко контролни клонове има в метода, толкова по-лесно е за JIT компилатора да въвежда променливи в регистри.

32. Постигайте малък размер и висока кохезивност на сглобки колкото е възможно повече

1. Поставете всички публични класове и класове с обща база в някои асембли, поставете класовете инструменти, които предоставят функции за публични класове, в една и съща асемблера, пакетирайте съответните публични интерфейси в свои собствени асембли и накрая обработете класовете, които са по хоризонталната позиция в приложението;
2. По принцип трябва да се създават два типа компоненти: единият е малка и агрегирана сборка със специфична функция, а другата е голяма и широка сборка с общи функции.

33. Ограничаване на видимостта на типовете

1. Използването на интерфейси за излагане на функциите на типовете може да улесни създаването на вътрешни класове без ограничаване на тяхната наличност извън асемблера;
2. Колкото по-малко публични типове са изложени на външния свят, толкова повече възможности имате за бъдещо разширяване и промяна.

34. Създаване на голямо-гранулиран уеб API

Това минимизира честотата и натоварването на транзакциите между машините, поставяйки големи операции и прецизни изпълнения на сървъра.

35. Пренаписването е по-добро от процесите на събития

1. Ако процесор за събития хвърли изключение, други процесори в веригата няма да бъдат извикани, но това няма да се случи с пренаписания виртуален метод.
2. Пренаписването е много по-ефективно от асоциативните процесори на събития, които трябва да итерират целия списък с заявки, което отнема повече време на процесора.
3. Събитията могат да се реагират по време на изпълнение, с по-голяма гъвкавост, и множество отговори могат да бъдат свързани с едно и също събитие.
4. Общото правило е да се работи с производно събитие, а методът на пренаписване е по-добър.

36. Справедливо използване. .NET диагностика по време на изпълнение

1. System.Diagnostics.Debug\Trace\EventLog предоставя всички необходими инструменти за добавяне на диагностична информация към runtime, а приложението може да записва в лога на системните събития, когато EventLog предостави съставката;
2. Накрая, не пишете собствена диагностична библиотека, .NET FCL вече има основната библиотека, от която се нуждаем.

37. Използвайте стандартни конфигурационни механизми

1、. Класът System.Windows.Application на .NET фреймуърка дефинира свойствата за установяване на общ конфигурационен път;
2. Application.LocalAppDataPath и Application.userDataPath ще генерират имената на пътищата на локалната директория с данни и потребителските данни;
3. Не записвайте данни в ProgramFiles и системни директории на Windows, тези места изискват по-високи разрешения за сигурност, не очаквайте потребителите да имат разрешения за запис.

38. Персонализиране и поддръжка на свързване на данни

1. Двата обекта BindingMananger и CurrencyManager реализират преноса на данни между контрола и източника на данни;
2. Предимства на свързването на данни: използването на свързване на данни е много по-лесно от писането на собствен код; Тя трябва да се използва за обхвати, различни от текстови елементи с данни – могат да се обвържат и други свойства на дисплея; За WindowsOS Forms обвързване на данни, възможността за обработка на многократна синхронизация на контролни източници на данни, свързани с проверки;
3. Когато обектът не поддържа необходимите атрибути, можете да поддържате обвързване на данни, като блокирате текущия обект и след това добавите желания обект.

39. Използвай. .NET валидация

1. В ASP.NET има пет контрола за проверка на валидността и можете да използвате CustomValidator, за да изведете нов клас и да добавите свой собствен автентикатор.
2. Валидирането на Windows изисква под-System.Windows.Forms.Control.Validating, за да се напише обработка на събития.

40. Изберете подходящия ** според нуждите

1. Масивът има два очевидни недостатъка: не може да бъде динамично преоразмерен; Преоразмеряването отнема време;
2. ArrayList смесва характеристиките на едномерни масиви и свързани списъци, Queue и Stack са специални масиви, базирани на Array;
3. Когато програмата е по-гъвкава за добавяне и изтриване на елементи, тя може да създава по-стабилни типове, а при създаване на клас, който симулира **, трябва да реализира индексатори и IEnumerable интерфейси за нея.

41. DataSet е по-добър от персонализирана структура

1. DataSets имат два недостатъка: взаимодействието между DataSets, използващи механизъм за сериализация в XML, и non-.NET код не е много добро; DataSet е много гъвкав контейнер;
2. Силните типове набори от данни нарушават повече правила за проектиране, а тяхната ефективност на разработка е много по-висока от тази на по-елегантните дизайни, написани от самите тях.

42. Използвайте характеристики за опростяване на отражението

Чрез проектиране и реализиране на класове функции, които принуждават разработчиците да декларират динамично използваеми типове, методи и атрибути, можете да намалите грешките по време на изпълнение и да подобрите удовлетвореността на софтуера.

43. Избягвайте прекомерна употреба на рефлекси

1. Параметрите и стойностите на връщането, използвани от членовете на Invoke, са System.Object, който конвертира типове по време на изпълнение, но възможността за проблеми е станала по-вероятна.
2. Интерфейсът ни позволява да получим по-ясна и по-поддържаема система, а отражението е много мощен механизъм за късно свързване. .NET фреймуърк го използва за реализиране на обвързване на данни за Windows контроли и уеб контроли.

44. Създайте специфични класове изключения за приложението

1. Единствената причина, поради която са необходими различни класове изключения, е да позволи на потребителите лесно да използват различни подходи към различни грешки при писане на catch processors;
2. Когато може да има различни поведения за поправка, трябва да създадем различни различни класове изключения, като предоставим всички конструктори, поддържани от базовия клас изключения, можем да създадем напълно функционален клас изключение за приложението и да използваме атрибута InnerException, за да запазим цялата информация за грешки, генерирана от по-ниско ниво на грешки.

45. Дайте приоритет на необичайните гаранции за безопасност

1. Силната гаранция за изключение осигурява най-добрия баланс между възстановяването от изключение и опростената обработка на изключения, като състоянието на програмата остава непроменено, когато операцията бъде прекъсната поради изключението.
2. Направете защитно копиране на данните, които ще бъдат модифицирани, модифицирайте защитното копие на тези данни, операцията в средата може да причини изключение и временното копие и оригиналният обект ще бъдат разменени;
3. Терминаторите, методите Dispose() и целевите методи, свързани с делегати, трябва да гарантират, че не хвърлят изключения при никакви обстоятелства.

46. Минимизирайте съвместимостта

1. Съществуват три разходи за съвместимост: разходите за изброяване на данни между управлявани и неуправлявани купчини, разходите за превключване между управляван код и неуправляван код и разработката на разработчиците, работещи с хибридни среди;
2. Използването на blitable тип в interop може ефективно да се репликира между управлявани и неуправлявани среди, без да бъде повлияно от вътрешната структура на обекта.
3. Използвайте функцията In/Out, за да осигурите най-подходящите, ненужни многократни репликации, и подобрете производителността чрез деклариране на начина, по който данните се изброяват.
4. Използвайте COM Interop за реализиране на съвместимост с COM компоненти по най-простия начин, използвайте P/Invoke за извикване на Win32 API или използвайте /CLR превключвателя на компилатора C++ за смесване на управляван и неуправляван код;

47. Дайте приоритет на комисиите за безопасност

1. Избягвайте достъпа до неуправлявана памет колкото е възможно повече, тъй като изолираното съхранение не може да предотврати достъпа от управляван код и доверени потребители.
2. Когато асемблерите работят в уеб, обмислете използването на изолирано съхранение, а когато определени алгоритми изискват по-високи разрешения за сигурност, тези кодове трябва да бъдат изолирани в отделен асемблер.

48. Овладейте релевантните инструменти и ресурси

1. Използване на NUnit за установяване на автоматични единични тестове (интегрирани във VS2010);
2. Инструментът FXCop ще получи IL кода в асемблера, ще го анализира спрямо хетерогенните правила и добри практики за кодиране и накрая ще докладва нарушението.
3. ILDasm е инструмент за разглобяване на Илинойс, който може да ни помогне да получим представа за детайлите;
4. Shared Source CLI е изходен код за реализация, който съдържа ядрото на .NET framework и компилатора на C#.




Предишен:Service Fabric - концепция за състояние на обслужване
Следващ:.net/c# SynchronizationContext за подробности
Отричане:
Целият софтуер, програмни материали или статии, публикувани от Code Farmer Network, са само за учебни и изследователски цели; Горното съдържание не трябва да се използва за търговски или незаконни цели, в противен случай потребителите ще понесат всички последствия. Информацията на този сайт идва от интернет, а споровете за авторски права нямат нищо общо с този сайт. Трябва напълно да изтриете горното съдържание от компютъра си в рамките на 24 часа след изтеглянето. Ако ви харесва програмата, моля, подкрепете оригинален софтуер, купете регистрация и получете по-добри услуги. Ако има нарушение, моля, свържете се с нас по имейл.

Mail To:help@itsvse.com