Ця стаття є дзеркальною статтею машинного перекладу, будь ласка, натисніть тут, щоб перейти до оригінальної статті.

Вид: 20516|Відповідь: 0

[Чайови] Сорок сім способів оптимізувати програму на C#

[Копіювати посилання]
Опубліковано 15.03.2018 10:41:59 | | |

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

1、. .NET зв'язування даних підтримує лише прив'язування даних, і ви можете отримати переваги зв'язування даних, використовуючи атрибути.
2. У режимі отримання та налаштування доступу до властивості можна заблокувати для додавання підтримки багатопоточності.

2. readonly (константа виконання часу) та const (константа часу компіляції)

1. const можна використовувати лише для примітивних типів, enum і рядків, тоді як readonly може бути будь-яким типом;
2. Const буде замінено на конкретну константу під час компіляції, так що якщо в посиланні використовуються і значення Const, і лише для читання, зміна на readonly змінить початкову мету дизайну — необхідність повторної компіляції зміненої асемблеру для повторного посилання на нове константне значення.
3. Const ефективніший за лише для читання, але втрачає гнучкість застосування.

3. IS і AS

1. Обидва варіанти є перетворенням типів під час виконання, оскільки оператори можуть використовуватися лише в еталонних типах, тоді як is може використовувати значення та типи посилання;
2. Зазвичай використовується IS для визначення типу, а потім вибірково використовувати оператор перетворення як або сильного типу (перетворення, визначене оператором).

4. ConditionalAttribute замість #if #endif条件编译

1. ConditionalAttribute використовується лише на рівні методу, а інші елементи, такі як типи, атрибути тощо, є недійсними. І #if #endif则不受此限制;
2. ConditionalAttribute може додавати кілька операцій OR (OR) для умов компіляції, і #if #endif则可以添加与(AND) [тут можна повністю визначити як окремий символ];
3. Визначення ConditioanlAttribute можна розмістити в окремому методі, щоб зробити програму більш гнучкою.

5. Надайте метод ToString()

1. Він може надавати детальну інформацію користувачам у більш дружній формі;
2. Використовуйте метод IFormatter.ToString() для більш гнучкого налаштування, і якщо додати інтерфейси IFormatProvider і ICustomFormater, буде логічніше налаштувати вихід повідомлення.

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

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; Виконання статичних ініціалізаторів поля; статичний конструктор, який виконує базовий клас; Статичні конструктори, які виконують поточний тип;
Встановіть усі поля екземплярів на 0; Виконати ініціалізатори полів екземпляра; Виконати відповідний конструктор екземпляру базового класу; Виконати конструктор екземпляра поточного типу.

15. Використовуйте оператори using і try/finally для очищення ресурсів

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

16. Мінімізація сміття пам'яті

1. Для розподілу та знищення об'єктів на купі потрібен додатковий час процесора;
2. Методи зменшення кількості призначених об'єктів: часто використовувані локальні змінні переходять у поля; Надає клас, що зберігає поширені екземпляри об'єктів Singleton, що виражають певні типи.
3. Використовуйте StringBuilder для виконання складних рядкових операцій.

17. Мінімізуйте пакування та розпакування

1. Зверніть увагу на неявне перетворення типу в System.Object, і значення не слід замінювати на System.Object тип;
2. Використання інтерфейсів замість типів дозволяє уникнути коробки, тобто реалізації типів значень з інтерфейсів, а потім виклику членів через інтерфейси.

18. Впровадити стандартний режим утилізації

1. Щоб використовувати ресурси, не пов'язані з пам'яттю, він повинен мати фіналізатор, збирач сміття додасть реалізовані фіналізаторні об'єкти до черги завершення після завершення об'єктів пам'яті, які їх не завершили, а потім збирач сміття запустить новий потік для запуску фіналайзерів на цих об'єктах. Це дозволяє уникнути проблеми витоку пам'яті, спричиненої некерованими ресурсами пам'яті, які не звільняються.
2. Використання методу IDisposable.Dispose() вимагає чотирьох аспектів роботи: звільнення всіх некерованих ресурсів; Звільніть усі керовані ресурси; Встановіть маркер статусу, щоб позначити, чи було виконано Dispose(); Викликайте GC.SuppressFinalize(this), щоб скасувати операцію завершення об'єкта;
3. Додати захищений віртуальний метод Dispose() до типу, який потребує поліморфізму, і похідний клас звільняє своє завдання, переписуючи цей метод.
4. У типі, що потребує ідентифікованого інтерфейсу, ми повинні реалізувати термінатор, навіть якщо він нам не потрібен.

19. Визначити та реалізувати інтерфейси над типами спадкування

1. Непов'язані типи можуть спільно реалізувати спільний інтерфейс, і реалізувати інтерфейс легше, ніж наслідування;
2. Інтерфейс є відносно стабільним, він інкапсулює набір функцій у інтерфейсі як інші типи контрактів на реалізацію, тоді як базовий клас може розширюватися з часом.

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

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

21. Використовуйте довірення для вираження зворотних дзвінків

1. Сам делегат не забезпечує жодного захоплення винятків, тому будь-який мультикаст-виклик делегата завершить весь ланцюжок викликів.
2. Відображуючи та викликаючи кожну цільову делегацію в ланцюжку делегатів, можна уникнути повернення мультикастних делегатів лише результату останнього делегата.

22. Використання подій для визначення зовнішніх інтерфейсів

1. Її слід оголосити як звичайну подію, і компілятор створює для нас методи додавання та переміщення.
2. Використовуйте контейнер System.ComponentModel.EventHandlerList для зберігання кожного обробника подій і використовуйте його для приховування складності всіх подій, коли тип містить велику кількість подій.

23. Уникайте повернення посилань на внутрішні класові об'єкти

1. Оскільки доступ до об'єкта типу значення створює копію об'єкта, атрибути визначення типу значення взагалі не змінять стан всередині об'єкта типу;
2. Константні типи можуть уникати зміни стану об'єкта;
3. Визначити інтерфейс для обмеження доступу до підмножини з метою мінімізації шкоди внутрішньому стану об'єкта.
4. Визначити об'єкт обгортки для обмеження доступу до іншого об'єкта;
5. Коли код клієнта змінює елементи внутрішньої інформації, можна реалізувати режим Observer, щоб об'єкт міг перевірити або відповідати змінам.

24. Декларативне програмування краще за імперативне програмування

Можна уникнути помилок у кількох схожих рукописних алгоритмах, а також забезпечити чіткий і читабельний код.

25. Реалізувати типи максимально серіалізованими

1. Тип не є керуванням інтерфейсу, вікном чи формою, і тип повинен підтримувати серіалізацію;
2. При додаванні десеріалізованого атрибута NonSerializedAttribute значення за замовчуванням може бути завантажене методом OnDeserialization(), який реалізує IDeserializationCallback;
3. У контролі версій можна використовувати інтерфейс ISerializable для гнучкого керування, а також надати конструктор серіалізації для ініціалізації об'єктів відповідно до даних у потоку, а також вимагати дозвіл на виключення SerializationFormatter при реалізації.
4. Якщо потрібно створити похідний клас, потрібно запропонувати метод гачка для похідного класу.

26. Використовуйте інтерфейси IComparable та IComparer для реалізації відношень сортування

1. Інтерфейс IComparable використовується для реалізації найбільш природного сортування типів, перевантаження чотирьох операторів порівняння та надання перевантаженої версії методу CompareTo() для прийняття певних типів як параметрів.
2. IComparer використовується для надання відношень сортування, які відрізняються від IComparable, або для надання сортувальних відношень, які сам тип стверджує, що не реалізовані.

27. Уникайте інтерфейсів, які можна уникати IC

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 надає всі інструменти, необхідні програмі для додавання діагностичної інформації до процесу виконання, і додаток може записувати у журнал системних подій, коли 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 — це спеціальні масиви, засновані на масиві;
3. Коли програма стає більш гнучкою у додаванні та видаленні елементів, вона може створювати більш надійні типи, а при створенні класу, що імітує **, має реалізовувати індексатори та інтерфейси IEnumerable для нього.

41. DataSet кращий за власну структуру

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

42. Використовуйте характеристики для спрощення відображення

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

43. Уникайте надмірного використання рефлексів

1. Параметри та значення повернення, які використовують учасники Invoke, — це System.Object, який конвертує типи під час виконання, але ймовірність виникнення проблем стала більш ймовірною.
2. Інтерфейс дозволяє отримати чіткішу та більш підтримувану систему, а відображення — це дуже потужний механізм пізнього зв'язування. .NET фреймворк використовує його для реалізації зв'язування даних для Windows та веб-елементів контролю.

44. Створіть специфічні класи винятків для додатку

1. Єдина причина, чому потрібні різні класи винятків, полягає в тому, щоб користувачі могли легко застосовувати різні підходи до різних помилок при написанні процесорів захоплення;
2. Коли можуть бути різні поведінки ремонту, слід створити різноманітні класи винятків, надаючи всі конструктори, підтримувані базовим класом винятків, ми можемо створити повністю функціональний клас винятків для додатку та використати атрибут InnerException для збереження всієї інформації про помилку, згенеровану нижчими рівнями помилки.

45. Надайте пріоритет ненормальним гарантіям безпеки

1. Гарантія сильних винятків забезпечує найкращий баланс між відновленням після виключення та спрощеним обробкою винятків, і стан програми залишається незмінним у разі переривання операції через виключення.
2. Зробити захисне копіювання даних, які підлягають зміні, змінити захисну копію цих даних, операція посередині може спричинити виняток, і тимчасова копія та оригінальний об'єкт будуть обміняні;
3. Термінатори, методи Dispose() та цільові методи, пов'язані з делегатами, повинні гарантувати, що вони не створюють винятків за жодних обставин.

46. Мінімізація сумісності

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

47. Надайте пріоритет кодам безпеки

1. Уникайте доступу до некерованої пам'яті настільки, наскільки це можливо, і ізольоване сховище не може запобігти доступу керованого коду та довірених користувачів.
2. Коли асемблери працюють у вебі, розгляньте використання ізольованого сховища, і якщо певні алгоритми вимагають вищих дозволів на безпеку, ці коди слід ізолювати в окремій асемблері.

48. Опануйте відповідні інструменти та ресурси

1. Використання NUnit для встановлення автоматичних юніт-тестів (інтегрованих у VS2010);
2. Інструмент FXCop отримає код IL у асемблері, проаналізує його відповідно до гетерогенних правил кодування та найкращих практик, і нарешті повідомить про порушення.
3. ILDasm — це інструмент для розбирання IL, який допомагає нам отримати уявлення про деталі;
4. Shared Source CLI — це вихідний код реалізації, який містить ядро .NET framework і компілятор C#.




Попередній:Service Fabric — концепція стану сервісу
Наступний:.net/c# SynchronizationContext для деталей
Застереження:
Усе програмне забезпечення, програмні матеріали або статті, опубліковані Code Farmer Network, призначені лише для навчання та досліджень; Вищезазначений контент не повинен використовуватися в комерційних чи незаконних цілях, інакше користувачі несуть усі наслідки. Інформація на цьому сайті надходить з Інтернету, і спори щодо авторських прав не мають до цього сайту. Ви повинні повністю видалити вищезазначений контент зі свого комп'ютера протягом 24 годин після завантаження. Якщо вам подобається програма, будь ласка, підтримуйте справжнє програмне забезпечення, купуйте реєстрацію та отримайте кращі справжні послуги. Якщо є будь-яке порушення, будь ласка, зв'яжіться з нами електронною поштою.

Mail To:help@itsvse.com