Quem gostou de ver o dinamismo trazido ao C# 4.0 vai gostar de ficar sabendo que ainda há alguns problemas na implementação não resolvidos pela Microsoft (quem não viu ainda eu já demonstrei o C# 4.0 dinâmico aqui no blog).

(Estou puxando do blog do Sam Ng. Se você prefere ler no original eu encorajo que o faça.)

Abaixo vou demonstrar alguns dos problemas atuais a serem resolvidos até o lançamento do C# 4.0 com relação ao dinamismo. São construções que no C# estático não chegam a causar a menor preocupação, mas no C# dinâmico trazem algumas rugas.

 

Alteração de valores em tipos dinâmicos:

Por causa de boxing e unboxing, e como todo tipo dinâmico é um objeto, esse tipo de operação:

static void Main()
{
    dynamic d = 10;
    d++;
}

Vai resultar em “d” com um valor igual a 10, e não 11. O valor é unboxed, alterado e não é trazido de volta. Já viu o bug no seu código, né? Isso é altamente contra-intuitivo.

Além disso, no CTP atual isso não funciona. Vejam o erro:

Dinamismo no C# pode ser um perigo

 

Alteração aninhada em tipos de valor:

O código a seguir também vai te enganar.

public struct S
{
    public int i;
}

public class D
{
    public S s;
    public static void Main()
    {
        dynamic d = new D();
        d.s = default(S);
        d.s.i = 10;
        Console.WriteLine(d.s.i);
    }
}

O valor escrito na console parece ser 10, mas na verdade é zero. Mesmo problema do item anterior, o valor de S é unboxed, e a variável “i” alterada na verdade é do objeto que foi unboxed, ou seja, o valor d.s.i ainda é zero. Maus um pau no seu código.

 

Nível de acesso dos membros:

Esse método vai falhar só porque é dinâmico:

public class C
{
    private void M(int x) { }

    static void Main()
    {
        dynamic d = 10;
        C c = new C();
        c.M(d);
    }
}

Se a variável “d” fosse um inteiro ele funcionaria. Ele falha porque, como d é uma variável dinâmica, a chamada a c.M é feita dinamicamente. Isso significa que em runtime o método M vai ser procurado e advinhem? como ele é privado não vai ser encontrado. Algo trivial ficou complicado. Resultado: bug, bug, bug. Na prática, o código nem compila.

Além disso, há outros problemas:

  1. Não é possível fazer chamadas em métodos que implementam interfaces explicitamente. Isso acontece porque o método é exposto somente via interface, e na classe que a implementa ele fica “escondido”. Como uma chamada dinâmica depende da visibilidade do método, chamadas a métodos que implementam interfaces explicitamente vão resultar em métodos não encontrados, ou, em outras palavras: bugs.
  2. Não é possível chamar métodos de classe base com parâmetros dinâmicos, porque em runtime o método é chamado dinamicamente, e sempre vai resolver para a classe filha.

Tudo parecia tão simples, não é? É sempre bom lembrar que quando se trata de linguagens e compiladores nada é óbvio. A Microsoft vai resolver os problemas, só não sabemos ainda como. De qualquer forma fiquem atentos porque independentemente da forma que for escolhida para resolver esses casos, você vai ter que entender o que está acontecendo. E o resultado pode ser tudo, menos trivial. E se você não souber o que está acontecendo já viu: bug, bug, bug.

Minha sugestão? Testes unitários! Pelo menos se você não entender o que está acontecendo o teste vai te mostrar onde os bugs estão.

Giovanni Bassi

Arquiteto e desenvolvedor, agilista, escalador, provocador. É fundador e CSA da Lambda3. Programa porque gosta. Acredita que pessoas autogerenciadas funcionam melhor e por acreditar que heterarquia é mais eficiente que hierarquia. Foi reconhecido Microsoft MVP há mais de dez anos, dos mais de vinte que atua no mercado. Já palestrou sobre .NET, Rust, microsserviços, JavaScript, TypeScript, Ruby, Node.js, Frontend e Backend, Agile, etc, no Brasil, e no exterior. Liderou grupos de usuários em assuntos como arquitetura de software, Docker, e .NET.