Що краще використовувати і чому для великого проекту:
#if DEBUG
public void SetPrivateValue(int value)
{ ... }
#endif
або
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value)
{ ... }
Що краще використовувати і чому для великого проекту:
#if DEBUG
public void SetPrivateValue(int value)
{ ... }
#endif
або
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value)
{ ... }
Відповіді:
Це дійсно залежить від того, що ти збираєшся:
#if DEBUG
: Код тут навіть не потрапить до IL при випуску.[Conditional("DEBUG")]
: Цей код надійде до ІЛ, однак виклики методу будуть опущені, якщо не встановлено DEBUG при компіляції абонента.Особисто я використовую обидва залежно від ситуації:
Умовний ("DEBUG") Приклад: я використовую це так, що мені не доведеться повертатися назад і редагувати свій код пізніше під час випуску, але під час налагодження я хочу бути впевненим, що я не робив помилок. Ця функція перевіряє, чи правильно я вводити ім’я властивості при спробі використовувати його в моїх матеріалах INotifyPropertyChanged.
[Conditional("DEBUG")]
[DebuggerStepThrough]
protected void VerifyPropertyName(String propertyName)
{
if (TypeDescriptor.GetProperties(this)[propertyName] == null)
Debug.Fail(String.Format("Invalid property name. Type: {0}, Name: {1}",
GetType(), propertyName));
}
Ви дійсно не хочете створювати функцію, використовуючи, #if DEBUG
якщо ви не готові завершити кожен виклик цієї функції однаково #if DEBUG
:
#if DEBUG
public void DoSomething() { }
#endif
public void Foo()
{
#if DEBUG
DoSomething(); //This works, but looks FUGLY
#endif
}
проти:
[Conditional("DEBUG")]
public void DoSomething() { }
public void Foo()
{
DoSomething(); //Code compiles and is cleaner, DoSomething always
//exists, however this is only called during DEBUG.
}
#if DEBUG Приклад: Я використовую це під час спроби встановити різні зв'язки для зв'язку WCF.
#if DEBUG
public const String ENDPOINT = "Localhost";
#else
public const String ENDPOINT = "BasicHttpBinding";
#endif
У першому прикладі код все існує, але просто ігнорується, якщо DEBUG не ввімкнено. У другому прикладі const ENDPOINT встановлюється на "Localhost" або "BasicHttpBinding" залежно від того, встановлено DEBUG чи ні.
Оновлення: Цю відповідь я оновлюю, щоб уточнити важливий і складний момент. Якщо ви вирішили скористатися програмою ConditionalAttribute
, майте на увазі, що під час компіляції виклики опущені, а не під час виконання . Це є:
MyLibrary.dll
[Conditional("DEBUG")]
public void A()
{
Console.WriteLine("A");
B();
}
[Conditional("DEBUG")]
public void B()
{
Console.WriteLine("B");
}
Коли бібліотека скомпільована в режимі випуску (тобто немає символу DEBUG), вона назавжди буде мати виклик B()
зсередини A()
, навіть якщо виклик до A()
нього включений, оскільки DEBUG визначений у виклику.
Ну, варто зазначити, що вони зовсім не означають одне і те ж.
Якщо символ DEBUG не визначений, то в першому випадку SetPrivateValue
сам виклик не буде викликаний ... тоді як у другому випадку він буде існувати, але будь-які абоненти , складені без символу DEBUG, ці дзвінки будуть опущені.
Якщо код і всі його викликаючі знаходяться в одній збірці, ця різниця є менш важливою - але це означає, що в першому випадку вам також потрібно мати #if DEBUG
навколо коду виклику .
Особисто я рекомендую другий підхід - але вам потрібно, щоб різниця між ними була чіткою в голові.
Я впевнений, що багато хто не погодиться зі мною, але, проводячи час, як будівельник, постійно чуючи "Але це працює на моїй машині!", Я вважаю точку зору, яку ви майже ніколи не використовуєте. Якщо вам дійсно потрібно щось для тестування та налагодження, знайдіть спосіб зробити цю перевіряність відокремленою від фактичного виробничого коду.
Абстрагуйте сценарії з глузуванням в одиничних тестах, складіть одноразові версії речей за одноразовими сценаріями, які ви хочете перевірити, але не вкладайте тести на налагодження в код для бінарних файлів, які ви протестуєте і записуйте для випуску продукції. Ці тести налагодження просто приховують можливі помилки від розробників, щоб їх не було знайдено пізніше.
#if debug
чи який-небудь подібний склад у своєму коді?
#if DEBUG
так, щоб ми випадково не спамували інших під час тестування системи, яка повинна передавати електронні листи в рамках процесу. Іноді це правильні інструменти для роботи :)
У першому прикладі, SetPrivateValue
не існуватиме в збірці , якщо DEBUG
не визначене, то з другим , наприклад, вимагає , щоб SetPrivateValue
не існуватиме в збірці , якщо DEBUG
не визначене.
У першому прикладі, вам доведеться обернути будь-які дзвінки SetPrivateValue
з #if DEBUG
а.
З другого прикладу, заклики до SetPrivateValue
програми будуть опущені, але майте на увазі, що SetPrivateValue
вони все ще будуть складені. Це корисно, якщо ви створюєте бібліотеку, тому додаток, що посилається на вашу бібліотеку, все ще може використовувати вашу функцію (якщо умова виконана).
Якщо ви хочете опустити виклики та заощадити простір виклику, ви можете використовувати комбінацію двох методів:
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value){
#if DEBUG
// method body here
#endif
}
#if DEBUG
навколо Conditional("DEBUG")
не видаляє дзвінки до цієї функції, вона просто видаляє функцію з IL, і тому у вас все ще виникають дзвінки до функції, яка не існує (помилки компіляції).
Припустимо, ваш код також мав #else
вислів, який визначав нульову функцію заглушки, звертаючись до одного з пунктів Джона Скіта. Існує друга важлива відмінність між ними.
Припустимо, що функція #if DEBUG
або Conditional
існує в DLL, на яку посилається ваш головний виконуваний проект. Використання#if
, оцінювання умовного буде виконано з урахуванням параметрів компіляції бібліотеки. Використовуючи Conditional
атрибут, оцінювання умовного буде виконано стосовно налаштувань компіляції виклику.
У мене є розширення SOAP WebService для реєстрації мережевого трафіку за допомогою користувацького [TraceExtension]
. Я використовую це лише для налагодження налагодження та пропуску з версій версій. Використовуйте атрибут, #if DEBUG
щоб обернути [TraceExtension]
атрибут, видаливши його з версій версій.
#if DEBUG
[TraceExtension]
#endif
[System.Web.Service.Protocols.SoapDocumentMethodAttribute( ... )]
[ more attributes ...]
public DatabaseResponse[] GetDatabaseResponse( ...)
{
object[] results = this.Invoke("GetDatabaseResponse",new object[] {
... parmeters}};
}
#if DEBUG
[TraceExtension]
#endif
public System.IAsyncResult BeginGetDatabaseResponse(...)
#if DEBUG
[TraceExtension]
#endif
public DatabaseResponse[] EndGetDatabaseResponse(...)
Зазвичай вам це знадобиться в Program.cs, де ви хочете вирішити запустити налагодження на коді, що не налагоджує, і в основному в службах Windows. Тому я створив поле для читання IsDebugMode і встановив його значення в статичному конструкторі, як показано нижче.
static class Program
{
#region Private variable
static readonly bool IsDebugMode = false;
#endregion Private variable
#region Constrcutors
static Program()
{
#if DEBUG
IsDebugMode = true;
#endif
}
#endregion
#region Main
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
if (IsDebugMode)
{
MyService myService = new MyService(args);
myService.OnDebug();
}
else
{
ServiceBase[] services = new ServiceBase[] { new MyService (args) };
services.Run(args);
}
}
#endregion Main
}