Qual é melhor usar e por que, em um projeto grande:
#if DEBUG
public void SetPrivateValue(int value)
{ ... }
#endif
ou
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value)
{ ... }
Qual é melhor usar e por que, em um projeto grande:
#if DEBUG
public void SetPrivateValue(int value)
{ ... }
#endif
ou
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value)
{ ... }
Respostas:
Realmente depende do que você procura:
#if DEBUG
: O código aqui nem chegará à IL no lançamento.[Conditional("DEBUG")]
: Este código alcançará o IL, no entanto, as chamadas para o método serão omitidas, a menos que DEBUG seja definido quando o chamador for compilado.Pessoalmente, uso os dois, dependendo da situação:
Exemplo condicional ("DEBUG"): Eu uso isso para não precisar voltar e editar meu código posteriormente durante o lançamento, mas durante a depuração, quero ter certeza de que não fiz nenhum erro de digitação. Essa função verifica se eu digito um nome de propriedade corretamente ao tentar usá-lo no meu material 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));
}
Você realmente não deseja criar uma função usando, a #if DEBUG
menos que esteja disposto a encerrar todas as chamadas dessa função com a mesma #if DEBUG
:
#if DEBUG
public void DoSomething() { }
#endif
public void Foo()
{
#if DEBUG
DoSomething(); //This works, but looks FUGLY
#endif
}
versus:
[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 Exemplo de DEBUG: eu uso isso ao tentar configurar ligações diferentes para a comunicação WCF.
#if DEBUG
public const String ENDPOINT = "Localhost";
#else
public const String ENDPOINT = "BasicHttpBinding";
#endif
No primeiro exemplo, todo o código existe, mas é apenas ignorado, a menos que DEBUG esteja ativado. No segundo exemplo, o const ENDPOINT é definido como "Localhost" ou "BasicHttpBinding", dependendo se DEBUG estiver definido ou não.
Atualização: Estou atualizando esta resposta para esclarecer um ponto importante e complicado. Se você optar por usar o ConditionalAttribute
, lembre-se de que as chamadas são omitidas durante a compilação e não o tempo de execução . Isso é:
MyLibrary.dll
[Conditional("DEBUG")]
public void A()
{
Console.WriteLine("A");
B();
}
[Conditional("DEBUG")]
public void B()
{
Console.WriteLine("B");
}
Quando a biblioteca é compilada contra o modo de versão (ou seja, nenhum símbolo de depuração), ele sempre terá a chamada para B()
dentro A()
omitido, mesmo se uma chamada para A()
está incluído porque DEBUG é definido na chamar montagem.
Bem, vale a pena notar que eles não significam a mesma coisa.
Se o símbolo DEBUG não estiver definido, no primeiro caso, o SetPrivateValue
próprio não será chamado ... enquanto no segundo caso existir, mas todos os chamadores que são compilados sem o símbolo DEBUG terão essas chamadas omitidas.
Se o código e todos os seus chamadores estiverem no mesmo assembly, essa diferença será menos importante - mas isso significa que, no primeiro caso, você também precisará ter também#if DEBUG
o código de chamada .
Pessoalmente, eu recomendaria a segunda abordagem - mas você precisa manter clara a diferença entre elas.
Tenho certeza de que muitos discordarão de mim, mas, tendo passado algum tempo como profissional de construção ouvindo constantemente "Mas funciona na minha máquina!", Entendo que você também nunca deve usar isso. Se você realmente precisa de algo para teste e depuração, descubra uma maneira de tornar essa testabilidade separada do código de produção real.
Abstraia os cenários com zombaria nos testes de unidade, faça versões únicas dos itens para os cenários que você deseja testar, mas não coloque testes de depuração no código dos binários que você testa e escreve para o release de produção. Esses testes de depuração apenas ocultam possíveis erros dos desenvolvedores, para que não sejam encontrados até mais tarde no processo.
#if debug
ou qualquer construção semelhante em seu código?
#if DEBUG
para não enviar spam acidentalmente a outros enquanto testamos um sistema que deve transmitir emails como parte do processo. Às vezes, essas são as ferramentas certas para o trabalho :)
Este também pode ser útil:
if (Debugger.IsAttached)
{
...
}
Debugger.IsAttached
deve ser chamado em tempo de execução, mesmo nas versões do release.
Com o primeiro exemplo, SetPrivateValue
não existirá na compilação se DEBUG
não estiver definido, com o segundo exemplo, chamadas para SetPrivateValue
não existirão na compilação se DEBUG
não estiver definido.
Com o primeiro exemplo, você vai ter que envolver todas as chamadas para SetPrivateValue
com #if DEBUG
tão bem.
Com o segundo exemplo, as chamadas para SetPrivateValue
serão omitidas, mas saiba que SetPrivateValue
elas ainda serão compiladas. Isso é útil se você estiver criando uma biblioteca, para que um aplicativo que faça referência à sua biblioteca ainda possa usar sua função (se a condição for atendida).
Se você deseja omitir as chamadas e economizar o espaço do chamado, você pode usar uma combinação das duas técnicas:
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value){
#if DEBUG
// method body here
#endif
}
#if DEBUG
Contornar Conditional("DEBUG")
não remove as chamadas para essa função, apenas remove a função da IL completamente, então você ainda está tendo chamadas para a função que não existe (erros de compilação).
Vamos supor que seu código também tenha uma #else
instrução que definiu uma função de stub nulo, abordando um dos pontos de Jon Skeet. Há uma segunda distinção importante entre os dois.
Suponha que a função #if DEBUG
ou Conditional
exista em uma DLL referenciada pelo executável do projeto principal. Usando o #if
, a avaliação do condicional será realizada com relação às configurações de compilação da biblioteca. Usando o Conditional
atributo, a avaliação do condicional será realizada com relação às configurações de compilação do invocador.
Eu tenho uma extensão SOAP WebService para registrar o tráfego de rede usando um costume [TraceExtension]
. Eu uso isso apenas para compilações de depuração e omitir das compilações de versão . Use o #if DEBUG
para quebrar o [TraceExtension]
atributo, removendo-o das compilações do Release .
#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(...)
Normalmente, você precisaria dele em Program.cs, onde deseja decidir executar o código Debug on Non-Debug e principalmente nos Serviços do Windows. Então, criei um campo somente leitura IsDebugMode e defina seu valor no construtor estático, como mostrado abaixo.
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
}