Por que Atributo condicional do .NET provocar efeitos secundários de ser removido?

StackOverflow https://stackoverflow.com/questions/410865

  •  03-07-2019
  •  | 
  •  

Pergunta

Eu li sobre o atributo Conditional hoje. De acordo com MSDN:

A aplicação ConditionalAttribute a um método indica a compiladores que uma chamada para o método não deve ser compilado em Microsoft Intermediate Language (MSIL) a menos que o símbolo de compilação condicional que está associado com ConditionalAttribute está definido.

OK. Isso é claro. Assim, a chamada para o método não será compilado. Mas o que sobre os efeitos colaterais?

[Conditional("UndefinedCondition")]
static void f1(int x) { Console.WriteLine(x); }

static int a = 0;
static void f2() { f1(++a); }

Assim, quando f2 é chamado, a chamada para f1 deve ser removido. Mas por que é ++a removidas também? Este does't faz qualquer sentido para mim!

Foi útil?

Solução

Expandindo resposta de Marc.

Este é definitivamente "By Design". A melhor maneira de entender a racionalização para isso é pensar sobre o que este código tomou o lugar de. Esta característica em muitos, e muito formas mais limpas, toma a forma de código condicionalmente compilado.

Por exemplo,

#if DEBUG
f1(++a);
#endif

Ou uma outra versão

#define f1(x) ...

No caso non-debug há claramente sem efeitos colaterais. Este é o mesmo comportamento para o código [condicional]. Concordo que é definitivamente não é tão claro como o primeiro exemplo, mas é tão claro como o segundo.

Outras dicas

Sim, todas as chamadas necessárias para argumentos são removidas também. Isto significa que para o caso de uso típico (compilações de depuração) você remove toda a expressão, que normalmente é o que se pretende.

Basicamente, você precisa ter muito cuidado ao usar métodos [Conditional], ou igualmente (em C # 3.0) métodos parciais - que têm um comportamento muito semelhante, se a outra metade do método parcial não é implementada. Como exemplo (para métodos parciais), ver abaixo. Note-se que a chamada para HasSideEffect() é removido (descomente a outra metade do Bar para vê-lo funcionar):

using System;
partial class Foo {
    partial void Bar(string value);
    static void Main() {
        Foo foo = new Foo();
        foo.Bar(HasSideEffect());
    }
    static string HasSideEffect() {
        Console.WriteLine("hello");
        return "world";
    }
}

partial class Foo {
    /* uncomment this
    partial void Bar(string value) {
        Console.WriteLine(value);
    }*/ 
}

Eu acho que é devido à facilidade de implementação do compilador.

Eu ficaria com medo de tal código de qualquer maneira (mesmo que trabalhou como você espera que ele) e escrevê-lo como

++a;
f1(a);

para maior clareza. Você sempre pode ver o que é executado eo que não é.

Eu também suspeito que este comportamento é projetado para ser o mesmo que C pré-processador macros, que normalmente são configurados para não avaliar os argumentos quando não estiver em uso.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top