É útil ao trabalhar com COM ou idiomas de tipo dinâmico. Por exemplo, se você usasse lua ou python para criar scripts para sua linguagem, é muito conveniente chamar o código de script como se fosse um código normal.
A palavra-chave dinâmica é nova no C # 4.0 e é usada para informar ao compilador que o tipo de uma variável pode ser alterado ou que não é conhecido até o tempo de execução. Pense nisso como sendo capaz de interagir com um Objeto sem precisar lançá-lo.
dynamic cust =GetCustomer();
cust.FirstName="foo";// works as expected
cust.Process();// works as expected
cust.MissingMethod();// No method found!
Observe que não precisamos lançar nem declarar cust como tipo Cliente. Como declaramos dinâmico, o tempo de execução assume o controle e, em seguida, pesquisa e define a propriedade FirstName para nós. Agora, é claro, quando você está usando uma variável dinâmica, está desistindo da verificação do tipo de compilador. Isso significa que a chamada cust.MissingMethod () será compilada e não falhará até o tempo de execução. O resultado dessa operação é uma RuntimeBinderException porque MissingMethod não está definido na classe Customer.
O exemplo acima mostra como a dinâmica funciona ao chamar métodos e propriedades. Outro recurso poderoso (e potencialmente perigoso) é poder reutilizar variáveis para diferentes tipos de dados. Tenho certeza de que os programadores Python, Ruby e Perl por aí podem pensar em um milhão de maneiras de tirar proveito disso, mas uso o C # há tanto tempo que parece "errado" para mim.
dynamic foo =123;
foo ="bar";
OK, então você provavelmente não escreverá código como o acima com muita frequência. Pode haver momentos, no entanto, em que a reutilização de variáveis pode ser útil ou limpar um pedaço sujo de código legado. Um caso simples em que me deparo frequentemente é a necessidade constante de converter entre decimal e duplo.
decimal foo =GetDecimalValue();
foo = foo /2.5;// Does not compile
foo =Math.Sqrt(foo);// Does not compilestring bar = foo.ToString("c");
A segunda linha não é compilada porque 2,5 é digitado como duplo e a linha 3 não é compilada porque Math.Sqrt espera um duplo. Obviamente, tudo o que você precisa fazer é converter e / ou alterar seu tipo de variável, mas pode haver situações em que a dinâmica faça sentido.
dynamic foo =GetDecimalValue();// still returns a decimal
foo = foo /2.5;// The runtime takes care of this for us
foo =Math.Sqrt(foo);// Again, the DLR works its magicstring bar = foo.ToString("c");
Pessoalmente, eu não gosto do pensamento de usar o dynamicin c # para resolver problemas que podem ser resolvidos (talvez até melhor) por recursos padrão de c # e digitação estática, ou no máximo com inferência de tipo ( var). sódynamic deve ser usado quando se trata de problemas de interoperabilidade com o DLR. Se você escrever código em uma linguagem estática, como c # is, faça-o e não emule uma linguagem dinâmica. Isso é apenas feio.
Philip Daubmeier
40
Se você faz uso pesado de dynamicvariáveis em seu código onde não precisa delas (como no exemplo com o squareroot), desiste da verificação de erros em tempo de compilação; agora você está recebendo possíveis erros de tempo de execução.
Philip Daubmeier
33
Principalmente bem, mas alguns erros menores. Primeiro, não é correto dizer que dinâmico significa que o tipo da variável pode mudar. A variável em questão é do tipo "dinâmico" (da perspectiva da linguagem C #; da perspectiva do CLR, a variável é do tipo objeto). O tipo de uma variável nunca muda. O tipo de tempo de execução do valor de uma variável pode ser qualquer tipo compatível com o tipo da variável. (Ou, no caso de tipos de referência, que pode ser nulo.)
Eric Lippert
15
Em relação ao seu segundo ponto: o C # já tinha o recurso de "criar uma variável na qual você pode colocar qualquer coisa" - você sempre pode criar uma variável do tipo objeto. O interessante da dinâmica é o que você aponta no seu primeiro parágrafo: a dinâmica é quase idêntica ao objeto, exceto que a análise semântica é adiada até o tempo de execução, e a análise semântica é feita no tipo de expressão em tempo de execução. (. Principalmente Há algumas exceções.)
Eric Lippert
18
Eu gastei um ponto de votação negativo sobre isso, principalmente porque está implicitamente defendendo o uso da palavra-chave para uso geral. Ele tem um objetivo específico (descrito perfeitamente na resposta de Lasses) e, embora essa resposta seja tecnicamente correta, é provável que desvie os desenvolvedores.
oito bits Guru
211
A dynamicpalavra-chave foi adicionada, juntamente com muitos outros novos recursos do C # 4.0, para facilitar a conversação com código que vive ou provém de outros tempos de execução, que possui APIs diferentes.
Veja um exemplo.
Se você possui um objeto COM, como o Word.Applicationobjeto, e deseja abrir um documento, o método para fazer isso é fornecido com pelo menos 15 parâmetros, a maioria dos quais é opcional.
Para chamar esse método, você precisaria de algo assim (estou simplificando, esse não é um código real):
Observe todos esses argumentos? Você precisa passar isso desde o C # antes da versão 4.0 não ter noção de argumentos opcionais. No C # 4.0, as APIs do COM foram facilitadas de trabalhar, apresentando:
named argument, can skip the rest
|
v
wordApplication.Documents.Open(@"C:\Test.docx",ReadOnly:true);^^||
notice no ref keyword, can pass
actual parameter values instead
A mágica é que o compilador C # agora injeta o código necessário e trabalha com novas classes no tempo de execução, para fazer quase exatamente a mesma coisa que você fez antes, mas a sintaxe foi oculta para você, agora você pode se concentrar no o que , e não tanto sobre como . Anders Hejlsberg gosta de dizer que você precisa invocar diferentes "encantamentos", que são uma espécie de trocadilho com a magia da coisa toda, onde você normalmente tem que agitar as mãos e dizer algumas palavras mágicas na ordem certa para conseguir um certo tipo de feitiço. A maneira antiga da API de conversar com objetos COM era muito disso; era necessário passar por muitos obstáculos para convencer o compilador a compilar o código para você.
As coisas se decompõem em C # antes da versão 4.0 ainda mais se você tentar falar com um objeto COM para o qual você não tem uma interface ou classe, tudo que você tem é uma IDispatchreferência.
Se você não sabe o que é, IDispatché basicamente uma reflexão para objetos COM. Com uma IDispatchinterface, você pode perguntar ao objeto "qual é o número de identificação do método conhecido como Salvar" e criar matrizes de um determinado tipo que contém os valores do argumento e, finalmente, chamar um Invokemétodo na IDispatchinterface para chamar o método, passando tudo as informações que você conseguiu reunir juntos.
O método Save acima pode se parecer com este (definitivamente não é o código certo):
é basicamente apenas C # alcançando VB em termos de expressividade, mas fazendo isso da maneira certa, tornando-o extensível, e não apenas para COM. Obviamente, isso também está disponível para o VB.NET ou qualquer outro idioma criado sobre o tempo de execução do .NET.
Você pode encontrar mais informações sobre a IDispatchinterface na Wikipedia: IDispatch, se quiser ler mais sobre ela. É uma coisa realmente sangrenta.
No entanto, e se você quisesse conversar com um objeto Python? Existe uma API diferente daquela usada para objetos COM e, como os objetos Python também são dinâmicos por natureza, você precisa recorrer à magia de reflexão para encontrar os métodos certos para chamar, seus parâmetros, etc., mas não o .NET reflexão, algo escrito para Python, praticamente como o código IDispatch acima, completamente diferente.
E para Ruby? Uma API diferente ainda.
JavaScript? O mesmo negócio, API diferente para isso também.
A palavra-chave dinâmica consiste em duas coisas:
A nova palavra-chave em C #, dynamic
Um conjunto de classes de tempo de execução que sabe como lidar com os diferentes tipos de objetos, que implementam uma API específica exigida pela dynamicpalavra - chave e mapeia as chamadas para a maneira correta de fazer as coisas. A API está até documentada; portanto, se você tiver objetos provenientes de um tempo de execução não coberto, poderá adicioná-lo.
A dynamicpalavra-chave não se destina, no entanto, a substituir qualquer código existente somente do .NET. Claro, você pode fazê-lo, mas não foi adicionado por esse motivo, e os autores da linguagem de programação C # com Anders Hejlsberg na frente foram os mais inflexíveis de que ainda consideram o C # como uma linguagem fortemente tipada e não sacrificam esse princípio.
Isso significa que, embora você possa escrever um código como este:
dynamic x =10;dynamic y =3.14;dynamic z ="test";dynamic k =true;dynamic l = x + y * z - k;
e compilá-lo, não era para ser uma espécie de sistema de mágica que permite descobrir o que você quis dizer em tempo de execução.
O objetivo era facilitar a conversa com outros tipos de objetos.
Há muito material na internet sobre a palavra-chave, proponentes, oponentes, discussões, reclamações, elogios etc.
Sugiro que você comece com os seguintes links e depois pesquise no Google:
Também é útil, além das APIs JSON do COM para web, em que a estrutura dos objetos JSON desserializados não é especificada em C #. Por exemplo , o método Decode de System.Web.Helpers.Json retorna um objeto dinâmico .
dumbledad
Além de "eles ainda consideram o C # como uma linguagem fortemente tipada": Eric Lippert não é fã de "fortemente tipada" como uma descrição.
Andrew Keeton
Eu discordo dele, mas é uma questão de opinião, não de fato. "Fortemente digitado" para mim significa que o compilador sabe, em tempo de compilação, que tipo é usado e, portanto, impõe as regras definidas em torno desses tipos. O fato de você poder optar por um tipo dinâmico que adia a verificação e a ligação de regras ao tempo de execução não significa, para mim, que o idioma seja digitado de maneira fraca. Normalmente, não contraste com tipagem forte com tipagem fraca, no entanto, costumo compará-la com tipagem dinâmica, como linguagens como Python, onde tudo é um pato até latir.
Lasse V. Karlsen
Qual é o objetivo desta resposta? Metade disso é sobre parâmetros opcionais e a interface IDispatch.
Xam
Foi por isso que dynamicfoi adicionado, para apoiar outros ecossistemas sobre como a invocação de método semelhante à reflexão pode ser feita, além de fornecer uma espécie de abordagem de caixa preta para estruturas de dados com uma maneira documentada de conseguir isso.
Lasse V. Karlsen
29
Estou surpreso que ninguém tenha mencionado vários despachos . A maneira usual de contornar isso é através do padrão Visitor e isso nem sempre é possível, então você acaba com isverificações empilhadas .
Então, aqui está um exemplo da vida real de uma aplicação minha. Em vez de fazer:
publicstaticMapDtoBaseCreateDto(ChartItem item){if(item isElevationPoint)returnCreateDtoImpl((ElevationPoint)item);if(item isMapPoint)returnCreateDtoImpl((MapPoint)item);if(item isMapPolyline)returnCreateDtoImpl((MapPolyline)item);//other subtypes followthrownewObjectNotFoundException("Counld not find suitable DTO for "+ item.GetType());}
Você faz:
publicstaticMapDtoBaseCreateDto(ChartItem item){returnCreateDtoImpl(item asdynamic);}privatestaticMapDtoBaseCreateDtoImpl(ChartItem item){thrownewObjectNotFoundException("Counld not find suitable DTO for "+ item.GetType());}privatestaticMapDtoBaseCreateDtoImpl(MapPoint item){returnnewMapPointDto(item);}privatestaticMapDtoBaseCreateDtoImpl(ElevationPoint item){returnnewElevationDto(item);}
Observe que, no primeiro caso, ElevationPointé uma subclasse de MapPointe, se não for colocada antesMapPoint , nunca será alcançada. Esse não é o caso da dinâmica, pois o método de correspondência mais próximo será chamado.
Como você pode imaginar, a partir do código, esse recurso foi útil enquanto eu realizava a tradução dos objetos ChartItem para suas versões serializáveis. Eu não queria poluir meu código com os visitantes e também não queria poluir meus ChartItemobjetos com atributos específicos de serialização inútil.
Não sabia sobre esse caso de uso. Um pouco hacky na melhor das hipóteses, no entanto. Isso jogará fora qualquer analisador estático.
Kugel
2
@ Kugel isso é verdade, mas eu não chamaria isso de hack . A análise estática é boa, mas eu não deixaria que ela me impedisse de uma solução elegante, onde as alternativas são: violação de princípio de aberto-fechado (padrão de visitante) ou aumento da complexidade ciclomática com o temido isempilhamento um em cima do outro.
Stelios Adamantidis
4
Bem, você tem a opção de correspondência de padrões com C # 7, não?
Kugel
2
Bem, os operadores são muito mais baratos dessa maneira (evitando a conversão dupla) e você recebe a análise estática de volta ;-) e o desempenho.
Kugel
@idbrii, por favor, não mude minhas respostas. Sinta-se à vontade para enviar um comentário e esclarecerei (se necessário), pois ainda estou ativo nesta comunidade. Além disso, por favor, não use magic; não existe mágica.
Stelios Adamantidis
11
Isso facilita a interoperabilidade entre as linguagens estáticas de tipo estáticas (CLR) e as dinâmicas (python, ruby ...) em execução no DLR (Dynamic Language Runtime), consulte MSDN :
Por exemplo, você pode usar o código a seguir para incrementar um contador em XML em C #.
E a mudança na VM necessária para a dinâmica realmente facilita os idiomas dinâmicos.
dykam
2
@ Tykam: Não há alterações na VM. O DLR funciona muito bem desde o .NET 2.0.
Jörg W Mittag
@ Jörg, sim, há uma mudança. O DLR é parcialmente reescrito porque agora a VM possui suporte para resolução dinâmica.
dykam
Eu estava um pouco otimista demais, a pesquisa mostrou que as mudanças não eram tão grandes.
Dykam 22/04
4
Um exemplo de uso:
Você consome muitas classes que possuem uma propriedade comum 'CreationDate':
publicclassContact{// some propertiespublicDateTimeCreationDate{get;set;}}publicclassCompany{// some propertiespublicDateTimeCreationDate{get;set;}}publicclassOpportunity{// some propertiespublicDateTimeCreationDate{get;set;}}
Se você escrever um método commun que recupere o valor da propriedade 'CreationDate', precisará usar a reflexão:
Ele será usado principalmente pelas vítimas de RAD e Python para destruir a qualidade do código, o IntelliSense e a detecção de erros em tempo de compilação.
Uma resposta cínica, mas facilmente verdadeira demais. Eu já vi isso simplesmente para evitar declarar estruturas com o resultado de que o código funciona se tudo estiver bem, mas explode sua pilha de maneiras imprevisíveis assim que você move o queijo.
AnthonyVO
Sim, você verá esse canto clássico cortando com muitos outros recursos de idioma. Não é de surpreender que você também veja aqui.
precisa saber é o seguinte
1
Ele é avaliado em tempo de execução, para que você possa mudar o tipo como em JavaScript para o que quiser. Isso é legítimo:
dynamic i =12;
i ="text";
E assim você pode alterar o tipo conforme necessário. Use-o como último recurso; é benéfico, mas ouvi muita coisa acontecendo nos bastidores em termos de IL gerada e que pode ter um preço de desempenho.
Eu hesitaria em dizer que é "legítimo". Ele certamente será compilado, portanto, é um "código legítimo" no sentido em que o compilador agora o compila e o tempo de execução o executa. Mas eu nunca gostaria de ver esse trecho de código específico (ou algo parecido com ele) em qualquer um dos códigos que mantenho, ou seria uma ofensa quase fatal.
Lasse V. Karlsen
6
Claro, mas isso teria sido "legítimo" com "objeto" em vez de "dinâmico". Você não mostrou nada de interessante sobre dinâmica aqui.
precisa
Para o objeto, você teria que convertê-lo no tipo apropriado, para realmente chamar qualquer um de seus métodos ... você perde a assinatura; você pode fazer com que seu código chame qualquer método sem erros de compilação e erros no tempo de execução. Estava com pressa de digitar, desculpe por não especificar. E @Lasse, eu concordo e provavelmente não usarei muito dinâmico.
Brian Mains
1
Caso Última uso resort não é explicado
denfromufa
1
O melhor caso de uso de variáveis do tipo 'dinâmico' para mim foi quando, recentemente, eu estava escrevendo uma camada de acesso a dados no ADO.NET ( usando SQLDataReader ) e o código estava invocando os procedimentos armazenados herdados já gravados. Existem centenas desses procedimentos armazenados herdados que contêm grande parte da lógica de negócios. Minha camada de acesso a dados precisava retornar algum tipo de dado estruturado à camada de lógica de negócios, baseada em C #, para fazer algumas manipulações ( embora quase não existam ). Todos os procedimentos armazenados retornam um conjunto diferente de dados ( colunas da tabela ). Então, em vez de criar dezenas de classes ou estruturas para armazenar os dados retornados e passá-los para o BLL, escrevi o código abaixo, que parece bastante elegante e arrumado.
publicstaticdynamicGetSomeData(ParameterDTO dto){dynamic result =null;stringSPName="a_legacy_stored_procedure";
using (SqlConnection connection =newSqlConnection(DataConnection.ConnectionString)){SqlCommand command =newSqlCommand(SPName, connection);
command.CommandType=System.Data.CommandType.StoredProcedure;
command.Parameters.Add(newSqlParameter("@empid", dto.EmpID));
command.Parameters.Add(newSqlParameter("@deptid", dto.DeptID));
connection.Open();
using (SqlDataReader reader = command.ExecuteReader()){while(reader.Read()){dynamic row =newExpandoObject();
row.EmpName= reader["EmpFullName"].ToString();
row.DeptName= reader["DeptName"].ToString();
row.AnotherColumn= reader["AnotherColumn"].ToString();
result = row;}}}return result;}
Você pode chamar linguagens dinâmicas como CPython usando pythonnet:
dynamic np = Py.Import("numpy")
Você pode transmitir genéricos ao dynamicaplicar operadores numéricos neles. Isso fornece segurança de tipo e evita limitações de genéricos. Isso é essencialmente * digitação de pato:
Outro caso de uso para dynamicdigitação é para métodos virtuais que enfrentam um problema de covariância ou contravariância. Um exemplo é o Clonemétodo infame que retorna um objeto do mesmo tipo que o objeto em que é chamado. Esse problema não é completamente resolvido com um retorno dinâmico, porque ignora a verificação de tipo estático, mas pelo menos você não precisa usar projeções feias o tempo todo, conforme o uso simples object. Caso contrário, para dizer, os elencos se tornam implícitos.
publicclass A
{// attributes and constructor herepublicvirtualdynamicClone(){var clone =new A();// Do more cloning stuff herereturn clone;}}publicclass B : A
{// more attributes and constructor herepublicoverridedynamicClone(){var clone =new B();// Do more cloning stuff herereturn clone;}}publicclassProgram{publicstaticvoidMain(){
A a =new A().Clone();// No cast needed here
B b =new B().Clone();// and here// do more stuff with a and b}}
Respostas:
A palavra-chave dinâmica é nova no C # 4.0 e é usada para informar ao compilador que o tipo de uma variável pode ser alterado ou que não é conhecido até o tempo de execução. Pense nisso como sendo capaz de interagir com um Objeto sem precisar lançá-lo.
Observe que não precisamos lançar nem declarar cust como tipo Cliente. Como declaramos dinâmico, o tempo de execução assume o controle e, em seguida, pesquisa e define a propriedade FirstName para nós. Agora, é claro, quando você está usando uma variável dinâmica, está desistindo da verificação do tipo de compilador. Isso significa que a chamada cust.MissingMethod () será compilada e não falhará até o tempo de execução. O resultado dessa operação é uma RuntimeBinderException porque MissingMethod não está definido na classe Customer.
O exemplo acima mostra como a dinâmica funciona ao chamar métodos e propriedades. Outro recurso poderoso (e potencialmente perigoso) é poder reutilizar variáveis para diferentes tipos de dados. Tenho certeza de que os programadores Python, Ruby e Perl por aí podem pensar em um milhão de maneiras de tirar proveito disso, mas uso o C # há tanto tempo que parece "errado" para mim.
OK, então você provavelmente não escreverá código como o acima com muita frequência. Pode haver momentos, no entanto, em que a reutilização de variáveis pode ser útil ou limpar um pedaço sujo de código legado. Um caso simples em que me deparo frequentemente é a necessidade constante de converter entre decimal e duplo.
A segunda linha não é compilada porque 2,5 é digitado como duplo e a linha 3 não é compilada porque Math.Sqrt espera um duplo. Obviamente, tudo o que você precisa fazer é converter e / ou alterar seu tipo de variável, mas pode haver situações em que a dinâmica faça sentido.
Leia mais sobre o recurso: http://www.codeproject.com/KB/cs/CSharp4Features.aspx
fonte
dynamic
in c # para resolver problemas que podem ser resolvidos (talvez até melhor) por recursos padrão de c # e digitação estática, ou no máximo com inferência de tipo (var
). sódynamic
deve ser usado quando se trata de problemas de interoperabilidade com o DLR. Se você escrever código em uma linguagem estática, como c # is, faça-o e não emule uma linguagem dinâmica. Isso é apenas feio.dynamic
variáveis em seu código onde não precisa delas (como no exemplo com o squareroot), desiste da verificação de erros em tempo de compilação; agora você está recebendo possíveis erros de tempo de execução.A
dynamic
palavra-chave foi adicionada, juntamente com muitos outros novos recursos do C # 4.0, para facilitar a conversação com código que vive ou provém de outros tempos de execução, que possui APIs diferentes.Veja um exemplo.
Se você possui um objeto COM, como o
Word.Application
objeto, e deseja abrir um documento, o método para fazer isso é fornecido com pelo menos 15 parâmetros, a maioria dos quais é opcional.Para chamar esse método, você precisaria de algo assim (estou simplificando, esse não é um código real):
Observe todos esses argumentos? Você precisa passar isso desde o C # antes da versão 4.0 não ter noção de argumentos opcionais. No C # 4.0, as APIs do COM foram facilitadas de trabalhar, apresentando:
ref
opcional para APIs COMA nova sintaxe para a chamada acima seria:
Veja como fica mais fácil, mais legível se torna?
Vamos separar isso:
A mágica é que o compilador C # agora injeta o código necessário e trabalha com novas classes no tempo de execução, para fazer quase exatamente a mesma coisa que você fez antes, mas a sintaxe foi oculta para você, agora você pode se concentrar no o que , e não tanto sobre como . Anders Hejlsberg gosta de dizer que você precisa invocar diferentes "encantamentos", que são uma espécie de trocadilho com a magia da coisa toda, onde você normalmente tem que agitar as mãos e dizer algumas palavras mágicas na ordem certa para conseguir um certo tipo de feitiço. A maneira antiga da API de conversar com objetos COM era muito disso; era necessário passar por muitos obstáculos para convencer o compilador a compilar o código para você.
As coisas se decompõem em C # antes da versão 4.0 ainda mais se você tentar falar com um objeto COM para o qual você não tem uma interface ou classe, tudo que você tem é uma
IDispatch
referência.Se você não sabe o que é,
IDispatch
é basicamente uma reflexão para objetos COM. Com umaIDispatch
interface, você pode perguntar ao objeto "qual é o número de identificação do método conhecido como Salvar" e criar matrizes de um determinado tipo que contém os valores do argumento e, finalmente, chamar umInvoke
método naIDispatch
interface para chamar o método, passando tudo as informações que você conseguiu reunir juntos.O método Save acima pode se parecer com este (definitivamente não é o código certo):
Tudo isso por apenas abrir um documento.
O VB tinha argumentos opcionais e suporte para a maioria disso fora da caixa há muito tempo, portanto, este código C #:
é basicamente apenas C # alcançando VB em termos de expressividade, mas fazendo isso da maneira certa, tornando-o extensível, e não apenas para COM. Obviamente, isso também está disponível para o VB.NET ou qualquer outro idioma criado sobre o tempo de execução do .NET.
Você pode encontrar mais informações sobre a
IDispatch
interface na Wikipedia: IDispatch, se quiser ler mais sobre ela. É uma coisa realmente sangrenta.No entanto, e se você quisesse conversar com um objeto Python? Existe uma API diferente daquela usada para objetos COM e, como os objetos Python também são dinâmicos por natureza, você precisa recorrer à magia de reflexão para encontrar os métodos certos para chamar, seus parâmetros, etc., mas não o .NET reflexão, algo escrito para Python, praticamente como o código IDispatch acima, completamente diferente.
E para Ruby? Uma API diferente ainda.
JavaScript? O mesmo negócio, API diferente para isso também.
A palavra-chave dinâmica consiste em duas coisas:
dynamic
dynamic
palavra - chave e mapeia as chamadas para a maneira correta de fazer as coisas. A API está até documentada; portanto, se você tiver objetos provenientes de um tempo de execução não coberto, poderá adicioná-lo.A
dynamic
palavra-chave não se destina, no entanto, a substituir qualquer código existente somente do .NET. Claro, você pode fazê-lo, mas não foi adicionado por esse motivo, e os autores da linguagem de programação C # com Anders Hejlsberg na frente foram os mais inflexíveis de que ainda consideram o C # como uma linguagem fortemente tipada e não sacrificam esse princípio.Isso significa que, embora você possa escrever um código como este:
e compilá-lo, não era para ser uma espécie de sistema de mágica que permite descobrir o que você quis dizer em tempo de execução.
O objetivo era facilitar a conversa com outros tipos de objetos.
Há muito material na internet sobre a palavra-chave, proponentes, oponentes, discussões, reclamações, elogios etc.
Sugiro que você comece com os seguintes links e depois pesquise no Google:
fonte
dynamic
foi adicionado, para apoiar outros ecossistemas sobre como a invocação de método semelhante à reflexão pode ser feita, além de fornecer uma espécie de abordagem de caixa preta para estruturas de dados com uma maneira documentada de conseguir isso.Estou surpreso que ninguém tenha mencionado vários despachos . A maneira usual de contornar isso é através do padrão Visitor e isso nem sempre é possível, então você acaba com
is
verificações empilhadas .Então, aqui está um exemplo da vida real de uma aplicação minha. Em vez de fazer:
Você faz:
Observe que, no primeiro caso,
ElevationPoint
é uma subclasse deMapPoint
e, se não for colocada antesMapPoint
, nunca será alcançada. Esse não é o caso da dinâmica, pois o método de correspondência mais próximo será chamado.Como você pode imaginar, a partir do código, esse recurso foi útil enquanto eu realizava a tradução dos objetos ChartItem para suas versões serializáveis. Eu não queria poluir meu código com os visitantes e também não queria poluir meus
ChartItem
objetos com atributos específicos de serialização inútil.fonte
is
empilhamento um em cima do outro.magic
; não existe mágica.Isso facilita a interoperabilidade entre as linguagens estáticas de tipo estáticas (CLR) e as dinâmicas (python, ruby ...) em execução no DLR (Dynamic Language Runtime), consulte MSDN :
O MSDN lista estas vantagens:
Veja MSDN para mais detalhes.
fonte
Um exemplo de uso:
Você consome muitas classes que possuem uma propriedade comum 'CreationDate':
Se você escrever um método commun que recupere o valor da propriedade 'CreationDate', precisará usar a reflexão:
Com o conceito 'dinâmico', seu código é muito mais elegante:
fonte
Interoperabilidade COM. Especialmente não conhecido. Foi projetado especialmente para isso.
fonte
Ele será usado principalmente pelas vítimas de RAD e Python para destruir a qualidade do código, o IntelliSense e a detecção de erros em tempo de compilação.
fonte
Ele é avaliado em tempo de execução, para que você possa mudar o tipo como em JavaScript para o que quiser. Isso é legítimo:
E assim você pode alterar o tipo conforme necessário. Use-o como último recurso; é benéfico, mas ouvi muita coisa acontecendo nos bastidores em termos de IL gerada e que pode ter um preço de desempenho.
fonte
O melhor caso de uso de variáveis do tipo 'dinâmico' para mim foi quando, recentemente, eu estava escrevendo uma camada de acesso a dados no ADO.NET ( usando SQLDataReader ) e o código estava invocando os procedimentos armazenados herdados já gravados. Existem centenas desses procedimentos armazenados herdados que contêm grande parte da lógica de negócios. Minha camada de acesso a dados precisava retornar algum tipo de dado estruturado à camada de lógica de negócios, baseada em C #, para fazer algumas manipulações ( embora quase não existam ). Todos os procedimentos armazenados retornam um conjunto diferente de dados ( colunas da tabela ). Então, em vez de criar dezenas de classes ou estruturas para armazenar os dados retornados e passá-los para o BLL, escrevi o código abaixo, que parece bastante elegante e arrumado.
fonte
dynamic np = Py.Import("numpy")
dynamic
aplicar operadores numéricos neles. Isso fornece segurança de tipo e evita limitações de genéricos. Isso é essencialmente * digitação de pato:T y = x * (dynamic)x
, Ondetypeof(x) is T
fonte
Outro caso de uso para
dynamic
digitação é para métodos virtuais que enfrentam um problema de covariância ou contravariância. Um exemplo é oClone
método infame que retorna um objeto do mesmo tipo que o objeto em que é chamado. Esse problema não é completamente resolvido com um retorno dinâmico, porque ignora a verificação de tipo estático, mas pelo menos você não precisa usar projeções feias o tempo todo, conforme o uso simplesobject
. Caso contrário, para dizer, os elencos se tornam implícitos.fonte