BT

Disseminando conhecimento e inovação em desenvolvimento de software corporativo.

Contribuir

Tópicos

Escolha a região

Início Notícias Futuro do C#: Defer

Futuro do C#: Defer

Mais conhecido por seu uso em Go e Swift, a proposta C# 1398 procura adicionar declarações de diferimento (defer) . Caso não esteja estiver familiarizado com o conceito, ele pode ser resumido como um bloco final que aparece no início de algum código em vez do final.

Aqui está um exemplo da proposta:

{
   SomeType thing = Whatever...;
   defer {
      thing.Free();
   }
   // some code code using thing
}

Isso seria interpretado como:

{
    SomeType thing = Whatever...;
    try
    {
        // some code code using thing
    }
    finally
    {
        thing.Free();
    }
}

Como isso se parece muito com um bloco final, muitos desenvolvedores acham que a sintaxe é redundante. Neal Gafter, da Microsoft, apresenta um contra-argumento afirmando que tem suas vantagens:

  • Eles não exigem a implementação de alguma interface, como IDisposable, ou a criação de objetos auxiliares.
  • Eles não adicionam um nível de recuo ao código, o que seria desajeitado quando há mais de um.
  • Eles não movem o código de limpeza para o final, como try-finally, mas mantêm o código de limpeza logicamente com a declaração e a inicialização da coisa que está sendo limpa. Dessa forma, eles facilitam o entendimento do código.

Alireza Habibi rejeita isso com:

Eu não acho que o problema real do uso da instrução seja de recuos adicionais nem que você tenha que implementar uma interface - isso não é uma coisa ruim, então existe um contrato para tipos que precisam de limpeza. Eu acho que o problema real aqui é que você pode esquecer de desprezar tipos descartáveis; adiar declaração não ajuda com isso, em vez disso, incentiva você a não implementar a interface IDisposable e explicitamente chamar métodos como Close ou Free, que na presença de IDisposable parecem códigos cheiros.

Sam também questiona a nova palavra-chave:

Se o caso de uso para defer é a limpeza de recursos, então parece ser um anti-pattern para eu não exigir que a coisa implemente IDisposable. A implementação de IDisposable permite que as ferramentas avisem se você criar uma variável descartável como local e nunca descartá-la. Se você aceitar os recursos para não exigir IDisposable, você perderá esse benefício.

Outra queixa é que dificulta a compreensão da ordem de operações. Um usuário que utiliza o identificador HaloFour oferece este exemplo:

static void Main() {
    Console.WriteLine("Hello"); //1
    defer {
        Console.WriteLine("Foo"); //5
    }
    defer {
        Console.WriteLine("Bar"); //4
    }
    defer {
        Console.WriteLine("Baz"); //3
    }
    Console.WriteLine("World"); //2
}

Para sua conveniência, a ordem em que as linhas serão executadas foram adicionadas como comentários. Como se pode ver, o código é executado de cima para baixo, pulando algumas linhas e, em seguida, de baixo para cima.

Exception Handling

Uma questão discutida é qual será o efeito de uma exceção em um bloco de defer. Com um try-finally normal, o bloco finally atual é abortado, mas outros blocos finally o envolvem ainda serão executados. Seria esse o caso para adiar ou a primeira falha faria com que os outros fossem contornados? O consenso geral parece ser que os blocos restantes de defer ainda serão executados.

O Swift evita esse problema ao não permitir código que possa lançar uma exceção a ser chamada de dentro de um bloco de adiamento.

No momento, a proposta da instrução defer está marcada como candidata C# 8.x, mas isso não significa que ela foi escolhida para fazer parte de uma versão futura do C#. Seu status oficial é "campeão de propostas", o que significa que um membro da equipe de C# está interessado em representar o recurso em uma futura reunião de design da linguagem (LDM).

Avalie esse artigo

Relevância
Estilo/Redação

Conteúdo educacional

BT