C#4: Nem tanto dinamismo assim?

Email

O código da questão do último post deve ter deixado muita gente de cabelo em pé, e por isso agradeço a todas as contribuições (feitas via Twitter, comentário, ou e-mail). A pergunta era:

Dado o seguinte código:

static int Funcao(int z) { return 1; }

static void Main()
{
   dynamic x = 3;
   DateTime y = Funcao(x);
}

O que deve acontecer?

  1. Não compila: tenho um erro em tempo de compilação na linha 6;
  2. Compila e em tempo de execução o inteiro é convertido para uma data usando uma conversão implícita no DLR;
  3. Compila e o inteiro é convertido para uma data usando uma conversão explícita do CLR, mas em tempo de compilação, com IL gerada pelo compilador na chamada da função;
  4. Compila mas tenho um erro em tempo de execução na linha 6, porque não é possível converter um inteiro para uma data.

A resposta correta, nada óbvia, é a quarta. Mas ela só não é óbvia se você não entende ainda como o C# 4 trabalha suas chamadas dinamicas. Vou explicar.

As chamadas dinâmicas se propagam. Quando você passou para o método "Funcao" um argumento dinâmico, toda a chamada passou a ser dinâmica, incluindo o retorno. O que há neste código, na verdade, é uma conversão no retorno de dinâmico para DateTime, porque dinâmico é conversível para qualquer tipo. Só que a conversão é feita em runtime. A "Funcao" sendo chamada parece obviamente ser a que está escrita na linha 1, mas o compilador não tem como saber. Pode ser que houvessem diversos outros métodos com o nome "Funcao" e que um deles retornasse algo que fosse possível converter para uma data. De qualquer forma, ao usar algo dinâmico, você efetivamente abandona qualquer checagem estática de tipos ou de chamadas de métodos em tempo de compilação. Como o argumento x era dinâmico, toda a chamada foi dinâmica.

Depois que entendemos isso fica óbvio. Antes, chega a parecer absurdo.

Email
Esse post foi publicado em Sem categoria e marcado por Giovanni Bassi. Marcar link permanente.

Sobre Giovanni Bassi

Arquiteto e desenvolvedor, agilista, pai, filho, namorado, escalador, provocador.
Programa porque gosta, e começou a trabalhar com isso porque acha que trabalhar como administrador é meio chato. Por esse motivo sempre diz que nunca mais vai virar gerente de ninguém. E também porque acredita que pessoas autogerenciadas funcionam melhor e por acreditar que heterarquia é melhor que hierarquia. Mas isso é outro assunto.
Foi reconhecido  Microsoft MVP depois que alguém notou que ele não dormia a noite pra ficar escrevendo artigos, cuidando e participando do .Net Architects, gravando o podcast Tecnoretórica, escrevendo posts no blog e falando o que bem entende no twitter @giovannibassi. E por falar nisso é no twitter que conta pra todos que gerencia de projetos deve ser feita pelo time e não por um gerentes, que greves em TI são coisas sem sentido e que stored procedure com regras de negócio são malígnas.
Você já deve ter percebido (até porque está lá na primeira frase) que Giovanni é agilista. De tanto gostar disso ele trouxe os programas de certificação e treinamento  PSD e PSM da Scrum.org pro Brasil, e por causa deles, do MVP e de algum trabalho que aparece tem que ficar indo pros EUA de vez enquando, coisa que prefere não fazer. (É bem comum você ouvir ele perguntando porque a Scrum.org e a Microsoft não estão na Itália, por exemplo.)
Junto com alguns Jedis criou a Lambda3, que, apesar de ser pequena e de não ser muito comum no Brasil, insiste em fazer projetos e consultoria direito. Por causa da Lambda3 ele tem trabalhado mais do que quando era consultor independente, mas menos do que a maioria das pessoas. Quer dizer, isso se você considerar que os trabalhos junto à comunidade não são trabalho, caso contrário ele trabalha mais que a maioria das pessoas.
Recentemente ele resolveu que merecia viver melhor e ganhar uns anos de vida e desistiu de ser sedentário, fazendo algum barulho de vez em quando com os amigos no twitter com a hashtag #DotNetEmForma. Por causa do convite recente de amigos do lado Open Source (que ele respeita e admira), começou a escalar, e agora está sempre com as mãos machucadas. Mas ainda dá pra programar. Você encontra ele sempre em algum evento, como o TechEd, e o DNAD, mas também outros menos comuns para o pessoal do .NET, como a RubyConf. Nesses eventos, ou ele está vendo palestras, ou batendo papo com alguém, ou codando alguma aplicação que alguém achou que dava pra fazer durante o evento.
  • Chan

    Só uma dúvida, o compilador não deveria entender que a “Funcao” retorna um int e não um dynamic ???
    Ao menos eu gostaria que fosse assim …..
    Se a “Funcao” retornasse um dynamic ai blz … poderia compilar
    static dynamic Funcao(int z) { return 1; }
    static void Main()
    {
    dynamic x = 3;
    DateTime y = Funcao(x);
    }
    mas ao passar um dynamic para o parametro da "Funcao", nao deveria mudar o tipo do retorno que no caso seria um int !
    mas pq o compilador entende que o retorno do metodo é um dynamic ? isso eu não entendi …
    Valeu Giovanni.

  • http://blog.fujiy.net/ Felipe Fujiy

    Fiquei com uma duvida por ser static.

    Chamadas static são sempre resolvidas em tempo de compilação, como é feita esta chamada?

  • http://unplugged.giggio.net/ Giovanni Bassi

    Chan, porque quando uma chamada é dinâmica, o compilador abandona qualquer ligação com os métodos que existem. Quando você passa um parametro dinamico, automaticamente ele entende que não sabe qual método você está chamando, e o retorno pode ser qualquer coisa.

    Felipe,
    Essa chamada é feita em tempo de execução. O compilador sequer sabe que a função chamada é estática. Ele vai resolver isso em runtime.

  • http://diogodamiani.com.br/ Diogo Damiani

    Andei lendo na internet e vi que existem várias questões quanto a utilização C# dinâmico, se ele permite fazer coisas como a demonstrada no desafio. Acho que uma grande sacada do C# dinâmico é simplificar a integração entre diversos ambientes e as linguagens dinâmicas facilitando a comunicação de classes .NET com classes não .NET.

    Um exemplo interessante, está na apresentação do Anders Hejlsberg no PDC 2008 onde ele manipula um controle VirtualEarth diretamente no C#, mas esse controle está escrito em JavaScript. Você já comentou sobre esse exemplo aqui no blog a algum tempo.

    Giovanni, quais as outras reais utilizações que você vê para o C# dinâmico?

  • http://unplugged.giggio.net/ Giovanni Bassi

    Todos os que as linguagens dinâmicas trazem.
    Que tal, por exemplo, polimorfismo sem herança?

  • http://theluxurywatchstore.biz/nautica/nautica-mens-bfc-chronograph-watch-n22505/ Nautica Mens Bfc Chronograph

    I like your blog curently we are looking for a part time article writer would you be interested?

  • http://theswisswatch.biz/seiko/seikoclock-qxm133brh/ Seikoclock Qxm133brh

    Please let me know if you are interested to work as article writer for me? I can offer $10/article.