C# - O tipo de dados Dynamic


A plataforma .NET introduziu na usa última versão um novo tipo de dados na linguagem C# 4.0.

Estou falando do tipo dynamic.

As linguagens dinâmicas foram muito populares na década de 80 sendo linguagens
versáteis usadas para programação via script onde não existia a verificação de tipos.
As linguagens PHP , Ruby e Phyton são exemplos de linguagens dinâmicas sendo menos prolixas e mais simples de usar.
Como o compilador só realiza a verificação do tipo em tempo de execução é necessário uma maior atenção do programador para evitar erros.
As linguagens IronPhyton e IronRuby são portes das linguagens Phyton e Ruby para a plataforma .NET sendo suportadas pelo DLR.
O Dynamic Language Runtime (DLR) da Microsoft é um esforço contínuo para trazer um conjunto de serviços que são executados em cima do Common Language Runtime (CLR) e fornece serviços de tradução para várias linguagens dinâmicas.

Abaixo vemos a figura que apresenta o DLR dando suporte as linguagens dinâmicas e ao recurso dynamic do C# 4.0:

O tipo dynamic é um tipo estático que é definido pela palavra reservada dynamic sendo que a princípio a variável desse tipo pode ser TUDO, e, em tempo de compilação o tipo dynamic assume qualquer operação.

Mesmo sendo um tipo estático a declaração dynamic faz com que o compilador não realize as validações estáticas sendo que as operações também somente serão avaliadas em tempo de execução.

A sua utilização ou não vai depender de cada caso e do cenário, e, como ele não dá suporte ao Intellisense você deve tomar muito cuidado ao usar esse tipo.

object , var e dynamic qual a diferença ????

- object e dynamic : são tipos;
- var :  é uma forma de inferir um tipo e somente variáveis podem ser declaradas;
-  object e var :  toda a informação do tipo/variável é conhecida em tempo de compilação;
- dynamic : a informação é conhecida somente em tempo de execução e pode ser aplicado a propriedades, retorno de métodos, parâmetros, objetos enfim a TUDO.
- object e var : são palavras reservadas enquanto que dynamic não é. Dessa forma se você definir uma variável chamada dynamic ela será compilada no C# 4.0.

Em linguagens como JavaScript e PHP, as variáveis são fracamente tipadas, e não há necessidade de declarar o tipo de dados que uma variável irá realizar, por isso não há restrições sobre os operadores ou métodos que pode utilizar, por exemplo, o código JavaScript abaixo pode ser usado sem problemas:

// código JavaScript 
var
 teste = "Macoratti";  
teste += 1;  
alert(teste);  
    resultado ==> Macoratti1

Se tentarmos executar o mesmo código usando as linguagens fortemente tipadas da plataforma .NET com C# ou VB .NET teríamos algo assim (usando C#):

// código C# 
static void Main(string[] args)
{
   object teste = "Macoratti";
   teste += 1;
   Console.WriteLine(teste);
   Console.ReadKey();
}
 

Mas Por quê ???

Embora a variável teste seja do tipo object e possa receber qualquer valor, quando atribuímos uma string à mesma, o compilador sabe que não podemos adicionar o valor 1 a uma string e por isso lança uma exceção em tempo de compilação;

Agora vejamos o mesmo código usando o tipo dynamic com a linguagem C# 4.0:

// código C# 4.0
static void Main(string[] args)
{
  dynamic teste = "Macoratti";
  teste += 1;
  Console.WriteLine(teste);
  Console.ReadKey();
}
   

O compilador agora exibe o resultado : Macoratti1 , pois a expressão teste +=1 , onde teste é um tipo dynamic, não é verificada em tempo de compilação.

As conversões entre os objetos dinâmicos e outros tipos são fáceis e isso permite ao desenvolvedor alternar entre o comportamento dinâmico e não dinâmicos.

Qualquer objeto pode ser convertido implicitamente para o tipo dynamic , conforme mostrado nos exemplos a seguir:

dynamic d1 = 7;
dynamic d2 = "a string";
dynamic d3 = System.DateTime.Today;
dynamic d4 = System.Diagnostics.Process.GetProcesses();

A conversão implícita também pode ser aplicada dinamicamente a qualquer expressão do tipo dynamic.

int i = d1;
string str = d2;
DateTime dt = d3;
System.Diagnostics.Process[] procs = d4;

O código completo é dado a seguir na aplicação console DynamicTipo:

using System;
namespace DynamicTipo
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic teste = "Macoratti";
            teste += 1;
            Console.WriteLine(teste);
            Console.ReadKey();
            dynamic d1 = 7;
            dynamic d2 = "a string";
            dynamic d3 = System.DateTime.Today;
            dynamic d4 = System.Diagnostics.Process.GetProcesses();
            Console.ReadKey();
            int i = d1;
            string str = d2;
            DateTime dt = d3;
            System.Diagnostics.Process[] procs = d4;
        }
    }
}

Um dos usos do tipo dynamic esta em melhorar a experiência de interagir com APIs COM, como a API  Office Automation.

Muitos métodos COM permitem a variação de tipos de argumentos e tipo de retorno, designando os tipos de objeto, isto obriga a conversão explícita dos valores para coordenar com variáveis fortemente tipadas em C #.

Se você compilar usando a opção /link, a introdução do tipo dinâmico permite que você trate as ocorrências de objeto COM em assinaturas, como se fossem do tipo dynamic, evitando assim a realização da conversão explícita (casting).

Para ilustrar, abaixo temos comandos que mostram como você pode acessar uma célula em uma planilha do Microsoft Excel com e sem a utilização do tipo dynamic:

Sem usar dynamic  Usando dynamic
((Excel.Range)excelApp.Cells[1, 1]).Value2 = "Nome";
Excel.Range range2008 = (Excel.Range)excelApp.Cells[1, 1];
 
 excelApp.Cells[1, 1].Value = "Nome";
 Excel.Range range2010 = excelApp.Cells[1, 1];
 

No exemplo onde usamos dynamic o acesso à propriedade Value e a conversão para Excel.Range são manipulados pelo binder COM em tempo de execução.

Antes de terminar quero lembrar que apesar do recurso dynamic a linguagem C# não é uma linguagem dinâmica.

Eu sei é apenas C# , mas eu gosto...

Referências:

José Carlos Macoratti