BT

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

Contribuir

Tópicos

Escolha a região

Início Notícias O futuro do C#: Anotações de closures

O futuro do C#: Anotações de closures

Embora esteja na lista de "algum interesse", a próxima proposta da série de evoluções do C# é bastante controversa. A premissa básica é que a proposta de listas de captura lambda permitirá maior controle sobre as variáveis capturadas em uma closure.

A proposta começa com listas de capturas, um conceito existente em C++. A seguir, está um exemplo com closure normal com uma lista de captura:

var x = 100;
Func a = () => x * 2;
Func b = [x] () => x * 2;

Ao utilizar esta sintaxe, qualquer variável que não esteja presente na lista de captura (denotada por abre e fecha colchetes, ex.: [x]) não pode ser utilizada em uma função anônima sem disparar um erro de compilação. Ao utilizar uma lista vazia, [], uma closure não será criada. Isto pode ajudar a melhorar o desempenho, uma vez que funções anônimas que não possuam closures não requerem alocação de memória.

Para acessar o objeto atual de dentro da closure, é utilizado o [this]. Isto reduz as ocorrências de capturas acidentais do objeto atual, o que pode gerar vazamentos de memória.

Captura por valor

Algumas vezes, queremos obter apenas uma cópia do valor dentro da closure ao invés de compartilhar uma variável. Nesta proposta, indica-se esta condição para o compilador utilizando a lista de captura:

Func c = [int xCopy = x]() => xCopy * 2;

Esta sintaxe é bastante verbosa e existem alternativas sugeridas para realizar a mesma ação:

Func d = [value x]() => x * 2; // x é uma cópia
Func e = [val x]() => x * 2; // x é uma cópia
Func f = [let x]() => x * 2; // x é uma cópia
Func g = [=x]() => x * 2; // x é uma cópia

Para tornar uma variável por referência de forma mais explícita em uma closure, a seguinte sintaxe foi proposta:

Func h = [ref x]() => x * 2; //x is an alias
Func i = [&x]() => x * 2; //x is an alias

A proposta "skinny arrow" (seta magra) é relacionada a esta ideia e determina que todas as variáveis sejam implicitamente capturadas por valor:

Func j = () -> x * 2; //this x is a copy

Capturas fracas

Como já mencionado anteriormente, closures cujo ciclo de vida ultrapassam o da função que as criaram são uma fonte comum de vazamento de memória. Portanto, Miguel de Icaza sugeriu que referências fracas fossem incluídas na proposta. Stephen Toub sugeriu esta sintaxe:

Action k = [weak myObject] () => […]
Action l = [weak this] () => […]
Action m = [wro = new WeakReference(myObject)] () => […]

Críticas

Como apresentado na introdução, esta proposta é controversa. Não importa quais variantes se escolha, esta nova sintaxe adiciona bastante ruído visual ao código. E, para closures curtas, ela não adiciona muito mais informação além da já existente.

A adição de listas de capturas deve ser realizada de maneira opcional para garantir retro-compatibilidade. Considerando o nível de burocracia da nova sintaxe, presume-se que a maioria dos programadores provavelmente não vá utilizá-la, o que coloca em dúvida a própria utilidade desta proposta.

Avalie esse artigo

Relevância
Estilo/Redação

Conteúdo educacional

BT