Теоретично статичний метод повинен працювати трохи краще, ніж метод екземпляра, при цьому всі інші речі рівні, через додатковий прихований this
параметр.
На практиці це має незначну різницю, що вона буде прихована в шумі різних рішень компілятора. (Отже, двоє людей могли «довести» одного кращого за іншого, не погоджуючись з результатами). Не в останню чергу, оскільки this
норма зазвичай передається в реєстр і часто є в цьому реєстрі для початку.
Останній пункт означає, що теоретично слід очікувати, що статичний метод, який приймає об'єкт як параметр і робить щось з ним, буде дещо менш хорошим, ніж еквівалент як екземпляр цього самого об'єкта. Знову ж таки, різниця настільки незначна, що якби ви спробували її виміряти, ви, ймовірно, в кінцевому підсумку виміряєте інше рішення компілятора. (Тим більше, що ймовірність того, що ця посилання весь час перебуває в реєстрі, теж досить висока).
Реальні відмінності в роботі знизяться до того, чи штучно ви отримали в пам'яті об'єкти, щоб зробити щось, що природно має стати статичним, або ви заплутуєте ланцюги передачі об'єктів складними способами робити те, що природно повинно бути екземпляром.
Отже, для числа 1. Якщо збереження стану не викликає занепокоєнь, завжди краще бути статичним, тому що саме для цього є статична . Це не стосується ефективності, хоча існує загальне правило, як грати добре з оптимізаціями компілятора - скоріше, що хтось піде на намагання оптимізувати випадки, які приходять у звичайне використання, ніж ті, які приходять із дивним використанням.
Число 2. Не має різниці. Існує певна сума вартості на кожен клас для кожного члена, що стосується як метаданих, скільки коду у фактичному файлі DLL чи EXE, так і скільки тривожного коду. Це те саме, будь то екземпляр чи статичний.
З пунктом 3, this
як this
і у випадку. Однак зверніть увагу:
this
Параметр передається в конкретному регістрі. При виклику методу екземпляра в межах одного класу він, ймовірно, вже буде в цьому реєстрі (якщо він не був прихованим і якийсь регістр використовується з якихось причин), і, отже, не потрібно вживати жодних дій, щоб встановити те, this
на що його потрібно встановити . Це певною мірою стосується, наприклад, перших двох параметрів методу, який є першими двома параметрами дзвінка, який він робить.
Оскільки буде зрозуміло, що this
це не нуль, це може використовуватися для оптимізації викликів у деяких випадках.
Оскільки буде зрозуміло, що this
це не нуль, це може зробити знову вбудовані виклики методу більш ефективними, оскільки код, створений для підробленого виклику методу, може пропустити деякі нульові перевірки, які можуть знадобитися в будь-якому випадку.
Однак, нульові чеки дешеві!
Варто зазначити, що загальні статичні методи, що діють на об’єкт, а не методи екземпляра, можуть зменшити деякі витрати, обговорені на веб-сторінці http://joeduffyblog.com/2011/10/23/on-generics-and-some-of- пов'язані накладні витрати / у випадку, коли дана статика не викликається для заданого типу. За його словами, «Убік, виявляється, що методи розширення є прекрасним способом зробити загальні абстракції більш оплатними.
Однак зауважте, що це стосується лише інстанції інших типів, використовуваних методом, які інакше не існують. Як такий, він дійсно не застосовується до багатьох випадків (якийсь інший метод екземпляра використовував цей тип, якийсь інший код десь інший використовував цей тип).
Підсумок:
- Здебільшого витрати на примірник порівняно зі статикою нижче незначні.
- Які витрати там, як правило, трапляються там, де ви зловживаєте статикою, наприклад, або навпаки. Якщо ви не зробите це частиною свого рішення між статикою та екземпляром, ви, швидше за все, отримаєте правильний результат.
- Є рідкісні випадки, коли статичні загальні методи в іншому типі призводять до створення меншої кількості типів, ніж примірних загальних методів, які можуть змусити іноді мати невелику користь для рідкісного використання (і "рідко" посилається на те, які типи використовуються в термін служби програми, а не те, як часто це називається). Як тільки ви отримаєте те, про що він говорить у цій статті, ви побачите, що це на 100% не має значення для більшості рішень щодо статичного проти екземпляра. Редагувати: І в основному це лише ціна з ngen, а не з jitted кодом.
Редагувати: примітка про те, наскільки дешеві нульові перевірки (на що я заявляла вище). Більшість недійсних перевірок у .NET взагалі не перевіряють на null, а вони продовжують робити те, що збиралися зробити, припускаючи, що воно буде працювати, і якщо трапляється виняток з доступу, він перетворюється на NullReferenceException
. Таким чином, здебільшого, коли концептуально код C # включає нульову перевірку, оскільки він отримує доступ до члена екземпляра, вартість, якщо він вдається, насправді дорівнює нулю. Виняток становлять деякі вбудовані дзвінки (тому що вони хочуть вести себе так, як ніби вони викликали члена екземпляра), і вони просто потрапляють у поле, щоб викликати таку саму поведінку, тому вони також дуже дешеві, і вони все ще часто можуть залишатися поза будь-яким чином (наприклад, якщо перший крок методу включав доступ до поля таким, яким він був).