Pergunta

Eu achei o seguinte, ao invés de estranho.Então, novamente, eu tenho usado principalmente de tampas em linguagens dinâmicas, que não deve ser suspectable para o mesmo "erro".A seguir faz com que o compilador infeliz:

VoidFunction t = delegate { int i = 0; };

int i = 1;

Ele diz:

Uma variável local chamada 'eu' não pode ser declarada neste âmbito, pois gostaria de dar um significado diferente para o 'eu', que já é usado em uma 'criança' escopo para denotar algo mais

Então, basicamente, isto significa que as variáveis declaradas dentro de um delegado terá o escopo da função declarada.Não é exatamente o que eu teria esperado.Eu havn't até que tentou chamar a função.Pelo menos Common Lisp possui um recurso onde você dizer que uma variável deve ter um nome dinâmico, se você realmente quer ser local.Isto é particularmente importante quando a criação de macros que não vazamento, mas algo como que seria útil aqui.

Então, eu estou querendo saber o que outras pessoas fazem para contornar este problema?

Para esclarecer, eu estou procurando uma solução onde as variáveis de eu declarar no delegete não interferir com as variáveis declaradas depois de o delegado.E eu quero ainda ser capaz de capturar as variáveis declaradas antes de o delegado.

Foi útil?

Solução

Tem que ser dessa forma para permitir que métodos anônimos (e lambdas) para usar variáveis locais e os parâmetros de escopo na caixa que contém o método.

As soluções alternativas são: ou usam nomes diferentes para a variável, ou criar uma ordinário método.

Outras dicas

O "fechamento" criado por uma função anônima é um pouco diferente da que criou em outras linguagens dinâmicas (eu vou usar o Javascript, por exemplo).

function thing() {
    var o1 = {n:1}
    var o2 = {dummy:"Hello"}
    return function() { return o1.n++; }
}

var fn = thing();
alert(fn());
alert(fn());

Este pequeno pedaço de javascript irá apresentar 1, 2.A função anônima pode acessar o o1 variável, pois ela existe em seu escopo corrente.No entanto, a função anônima tem um completamente independente do âmbito em que ele poderia criar outro o1 variável e, assim, ocultar quaisquer outros ainda mais o escopo da cadeia.Note-se também que todas as variáveis em toda a cadeia permanecem, portanto, o2 iria continuar a existir, mantendo uma referência de objeto, enquanto a combinação de teclas fn varialbe mantém a função de referência.

Agora compare com C# funções anônimas:-

class C1 { public int n {get; set;} }
class C2 { public string dummy { get; set; } }

Func<int> thing() {
   var o1 = new C1() {n=1};
   var o2 = new C2() {dummy="Hello"};
   return delegate { return o1.n++; };
}
...
Func<int> fn = thing();
Console.WriteLine(fn());
Console.WriteLine(fn());

Neste caso, a função anônima não é a criação de um verdadeiramente independente âmbito mais do que qualquer declaração de variável em qualquer outro em função { } bloco de código seria usado em um foreach, if, etc.)

Portanto, as mesmas regras se aplicam, do código de fora do bloco não é possível acessar variáveis declaradas dentro do bloco, mas não é possível reutilizar um identificador de ambos.

Um fecho é criado quando a função anônima é passado fora da função em que ele foi criado.A variação do Javascript exemplo é que apenas as variáveis que, na verdade, usado pela função anônima permanecerá, portanto, neste caso, o objeto realizado pela o2 estará disponível para GC assim que a coisa completa,

Você também terá CS0136 de código como este:

  int i = 0;
  if (i == 0) {
    int i = 1;
  }

O escopo da 2ª declaração de "eu" é inequívoca, linguagens como C++ não tem qualquer carne com ele.Mas a linguagem C# designers decidiu proibi-lo.Dado o fragmento acima, você acha que ainda acho que foi uma má ideia?Jogar um monte de código extra e você poderia olhar esse código por um tempo e não ver o erro.

A solução é simples e indolor, basta vir com um nome de variável diferente.

É porque o delegado pode fazer referência a variáveis fora do delegado:

int i = 1;
VoidFunction t = delegate { Console.WriteLine(i); };

Se eu me lembro corretamente, o compilador cria um membro da classe das variáveis externas referenciada no método anônimo, a fim de fazer este trabalho.

Aqui está uma solução:

class Program
    {
        void Main()
        {
            VoidFunction t = RealFunction;
            int i = 1;
        }
        delegate void VoidFunction();
        void RealFunction() { int i = 0; }
    } 

Na verdade, o erro não parece ter nada a ver com o anônimo delegados ou lamda expressões.Se você tentar compilar o seguinte programa ...

using System;

class Program
{
    static void Main()
    {
        // Action t = delegate
        {
            int i = 0;
        };

        int i = 1;
    }
}

...você obtenha exatamente o mesmo erro, não importa se você faz um comentário na linha ou não.O ajuda erro mostra um caso semelhante.Eu acho que é razoável a não permitir ambos os casos, sob o fundamento de que os programadores podiam confundir as duas variáveis.

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