Es útil cuando se trabaja con COM o idiomas escritos dinámicamente. Por ejemplo, si usaría lua o python para escribir su lenguaje, es muy conveniente llamar al código de scripting como si fuera un código normal.
La palabra clave dinámica es nueva en C # 4.0 y se usa para decirle al compilador que el tipo de una variable puede cambiar o que no se conoce hasta el tiempo de ejecución. Piense en ello como si pudiera interactuar con un Objeto sin tener que lanzarlo.
dynamic cust =GetCustomer();
cust.FirstName="foo";// works as expected
cust.Process();// works as expected
cust.MissingMethod();// No method found!
Tenga en cuenta que no necesitamos emitir ni declarar al cliente como tipo Cliente. Debido a que lo declaramos dinámico, el tiempo de ejecución se hace cargo y luego busca y establece la propiedad FirstName para nosotros. Ahora, por supuesto, cuando está utilizando una variable dinámica, está renunciando a la verificación del tipo de compilador. Esto significa que la llamada cust.MissingMethod () se compilará y no fallará hasta el tiempo de ejecución. El resultado de esta operación es una RuntimeBinderException porque MissingMethod no está definido en la clase Customer.
El ejemplo anterior muestra cómo funciona la dinámica al llamar a métodos y propiedades. Otra característica poderosa (y potencialmente peligrosa) es poder reutilizar variables para diferentes tipos de datos. Estoy seguro de que los programadores de Python, Ruby y Perl pueden pensar en un millón de maneras de aprovechar esto, pero he estado usando C # tanto tiempo que me parece "incorrecto".
dynamic foo =123;
foo ="bar";
OK, lo más probable es que no escribas código como el anterior muy a menudo. Sin embargo, puede haber ocasiones en que la reutilización de variables pueda ser útil o limpiar una pieza sucia de código heredado. Un caso simple con el que me encuentro a menudo es tener que emitir constantemente entre decimal y doble.
decimal foo =GetDecimalValue();
foo = foo /2.5;// Does not compile
foo =Math.Sqrt(foo);// Does not compilestring bar = foo.ToString("c");
La segunda línea no se compila porque 2.5 se escribe como doble y la línea 3 no se compila porque Math.Sqrt espera un doble. Obviamente, todo lo que tiene que hacer es emitir y / o cambiar su tipo de variable, pero puede haber situaciones en las que sea dinámico usarlo.
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");
Personalmente, no me gusta la idea de usar dynamicin c # para resolver problemas que pueden resolverse (tal vez incluso mejor) mediante las características estándar de c # y la escritura estática, o como máximo con inferencia de tipos ( var). dynamicdebe solamente ser utilizado cuando se trata de cuestiones interoperabilty con el DLR. Si escribe código en un lenguaje tipado estático, como c # is, entonces hágalo y no emule un lenguaje dinámico. Eso es simplemente feo.
Philip Daubmeier
40
Si hace un uso intensivo de las dynamicvariables en su código donde no las necesita (como en su ejemplo con la raíz cuadrada), abandona la comprobación de errores de tiempo de compilación limpio; en cambio, ahora está recibiendo posibles errores de tiempo de ejecución.
Philip Daubmeier
33
Mayormente bien, pero un par de errores menores. Primero, no es correcto decir que dinámico significa que el tipo de variable puede cambiar. La variable en cuestión es de tipo "dinámico" (desde la perspectiva del lenguaje C #; desde la perspectiva del CLR, la variable es de tipo objeto). El tipo de una variable nunca cambia. El tipo de tiempo de ejecución del valor de una variable puede ser cualquier tipo compatible con el tipo de la variable. (O en el caso de los tipos de referencia, puede ser nulo.)
Eric Lippert
15
Con respecto a su segundo punto: C # ya tenía la función de "crear una variable en la que pueda poner cualquier cosa", siempre puede crear una variable de tipo objeto. Lo interesante de dinámico es lo que señala en su primer párrafo: dinámico es casi idéntico al objeto, excepto que el análisis semántico se difiere hasta el tiempo de ejecución, y el análisis semántico se realiza sobre el tipo de tiempo de ejecución de la expresión. (Mayormente. Hay algunas excepciones.)
Eric Lippert
18
He gastado un punto negativo en esto, principalmente porque está abogando implícitamente por el uso de la palabra clave para uso general. Tiene un propósito específico (descrito perfectamente en la respuesta de Lasses) y aunque esta respuesta es técnicamente correcta, es probable que extravíe a los desarrolladores.
Eight-Bit Guru
211
La dynamicpalabra clave se agregó, junto con muchas otras características nuevas de C # 4.0, para que sea más fácil hablar con el código que vive o proviene de otros tiempos de ejecución, que tiene diferentes API.
Toma un ejemplo.
Si tiene un objeto COM, como el Word.Applicationobjeto, y desea abrir un documento, el método para hacerlo viene con no menos de 15 parámetros, la mayoría de los cuales son opcionales.
Para llamar a este método, necesitaría algo como esto (estoy simplificando, este no es el código real):
Tenga en cuenta todos esos argumentos? Debe pasarlos ya que C # antes de la versión 4.0 no tenía una noción de argumentos opcionales. En C # 4.0, las API COM se han hecho más fáciles de trabajar al introducir:
¿Ves cuánto más fácil se ve, cuánto más legible se vuelve?
Vamos a separar eso:
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
La magia es que el compilador de C # ahora inyectará el código necesario y trabajará con nuevas clases en el tiempo de ejecución, para hacer casi exactamente lo mismo que antes, pero la sintaxis se le ha ocultado, ahora puede concentrarse en el qué , y no tanto sobre cómo . A Anders Hejlsberg le gusta decir que tienes que invocar diferentes "encantamientos", que es una especie de juego de palabras con la magia de todo el asunto, en el que normalmente tienes que agitar las manos y decir algunas palabras mágicas en el orden correcto. para poner en marcha cierto tipo de hechizo. La antigua forma de API de hablar con objetos COM era mucho de eso, necesitabas saltar muchos aros para convencer al compilador de que compilara el código por ti.
Las cosas se descomponen en C # antes de la versión 4.0 aún más si intentas hablar con un objeto COM para el que no tienes una interfaz o clase, todo lo que tienes es una IDispatchreferencia.
Si no sabe qué es, IDispatches básicamente un reflejo para los objetos COM. Con una IDispatchinterfaz, puede preguntarle al objeto "cuál es el número de identificación del método conocido como Guardar", y construir matrices de cierto tipo que contengan los valores del argumento, y finalmente llamar a un Invokemétodo en la IDispatchinterfaz para llamar al método, pasando todo la información que has logrado buscar juntos.
El método Save anterior podría verse así (definitivamente este no es el código correcto):
es básicamente solo C # ponerse al día con VB en términos de expresividad, pero hacerlo de la manera correcta, al hacerlo extensible, y no solo para COM. Por supuesto, esto también está disponible para VB.NET o cualquier otro lenguaje creado sobre el tiempo de ejecución de .NET.
Puede encontrar más información sobre la IDispatchinterfaz en Wikipedia: IDispatch si desea leer más al respecto. Es realmente algo sangriento.
Sin embargo, ¿qué pasaría si quisieras hablar con un objeto de Python? Hay una API diferente para la que se usa para los objetos COM, y dado que los objetos de Python también son de naturaleza dinámica, debe recurrir a la magia de reflexión para encontrar los métodos correctos para llamar, sus parámetros, etc. pero no el .NET Reflexión, algo escrito para Python, muy parecido al código IDispatch anterior, simplemente completamente diferente.
¿Y para Ruby? Una API diferente todavía.
JavaScript? Mismo trato, API diferente para eso también.
La palabra clave dinámica consta de dos cosas:
La nueva palabra clave en C #, dynamic
Un conjunto de clases de tiempo de ejecución que sabe cómo lidiar con los diferentes tipos de objetos, que implementan una API específica que dynamicrequiere la palabra clave y asigna las llamadas a la forma correcta de hacer las cosas. La API incluso está documentada, por lo que si tiene objetos que provienen de un tiempo de ejecución no cubierto, puede agregarlo.
La dynamicpalabra clave no está, sin embargo, la intención de reemplazar cualquier código .NET de sólo existente. Claro, puede hacerlo, pero no se agregó por esa razón, y los autores del lenguaje de programación C # con Anders Hejlsberg en el frente, han insistido firmemente en que todavía consideran que C # es un lenguaje fuertemente tipado y no sacrificarán ese principio
Esto significa que aunque puede escribir código como este:
dynamic x =10;dynamic y =3.14;dynamic z ="test";dynamic k =true;dynamic l = x + y * z - k;
y compilarlo, no fue concebido como una especie de sistema de magia que permite descubrir qué querías decir en tiempo de ejecución.
Todo el propósito era facilitar el hablar con otros tipos de objetos.
Hay mucho material en Internet sobre la palabra clave, los proponentes, los opositores, las discusiones, las críticas, los elogios, etc.
Le sugiero que comience con los siguientes enlaces y luego busque en Google más:
También es útil además de COM para las API JSON web donde la estructura de los objetos JSON deserializados no se especifica en C #. Por ejemplo , el método Decode de System.Web.Helpers.Json devuelve un objeto dinámico .
Dumbledad
Un comentario aparte sobre "todavía consideran a C # como un lenguaje fuertemente tipado": Eric Lippert no es fanático de "fuertemente tipado" como descripción.
Andrew Keeton el
No estoy de acuerdo con él, pero es una cuestión de opinión, no una cuestión de hecho. Para mí, "fuertemente tipado" significa que el compilador sabe, en el momento de la compilación, qué tipo se utiliza y, por lo tanto, aplica las reglas establecidas en torno a esos tipos. El hecho de que pueda optar por un tipo dinámico que posponga la comprobación de reglas y la vinculación al tiempo de ejecución no significa, para mí, que el idioma esté tipeado débilmente. Por lo general, no contraste con tipeado fuerte con tipeado débil, sin embargo, generalmente lo comparo con tipeado dinámicamente, como lenguajes como Python, donde todo es un pato hasta que ladra.
Lasse V. Karlsen
¿Cuál es el punto de esta respuesta? La mitad es sobre parámetros opcionales y la interfaz IDispatch.
Xam
Es por eso que dynamicse agregó, para apoyar a otros ecosistemas sobre cómo se puede realizar la invocación de métodos de reflexión, así como proporcionar una especie de enfoque de recuadro negro a las estructuras de datos con una forma documentada de lograr esto.
Lasse V. Karlsen
29
Me sorprende que nadie haya mencionado el envío múltiple . La forma habitual de evitar esto es a través del patrón de visitante y eso no siempre es posible, por lo que terminas con ischeques apilados .
Así que aquí hay un ejemplo de la vida real de una aplicación propia. En lugar de hacer:
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());}
Tú lo haces:
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);}
Tenga en cuenta que en el primer caso ElevationPointes una subclase de MapPointy si no se coloca antesMapPoint , nunca será alcanzado. Este no es el caso con dinámico, ya que se llamará al método de coincidencia más cercano.
Como puede adivinar por el código, esa característica fue útil mientras realizaba la traducción de objetos ChartItem a sus versiones serializables. No quería contaminar mi código con visitantes y tampoco quería contaminar mis ChartItemobjetos con atributos específicos de serialización inútiles.
No sabía sobre este caso de uso. Un poco hacky en el mejor de los casos, sin embargo. Lanzará cualquier analizador estático.
Kugel
2
@ Kugel eso es cierto, pero no lo llamaría un hack . El análisis estático es bueno, pero no dejaría que me impida una solución elegante, donde las alternativas son: violación de principio abierto-cerrado (Patrón de visitante) o mayor complejidad ciclomática con temible isapilado uno encima del otro.
Stelios Adamantidis
44
Bueno, tienes la opción de combinar patrones con C # 7, ¿no?
Kugel
2
Bueno, los operadores son mucho menos costosos de esa manera (evitando el doble lanzamiento) y obtienes un análisis estático de vuelta ;-) y el rendimiento.
Kugel
@idbrii por favor no cambies mis respuestas. Siéntase libre de dejar un comentario y aclararé (si es necesario) ya que todavía estoy activo en esta comunidad. Además, por favor no use magic; no hay tal cosa como magia.
Stelios Adamantidis
11
Facilita la interoperabilidad de los lenguajes de tipo estático (CLR) con los dinámicos (python, ruby ...) que se ejecutan en el DLR (tiempo de ejecución del lenguaje dinámico), consulte MSDN :
Por ejemplo, puede usar el siguiente código para incrementar un contador en XML en C #.
Y el cambio que requirió la VM para la dinámica en realidad facilita los lenguajes dinámicos.
Dykam
2
@Dykam: No hay cambios en la VM. El DLR funciona bien de regreso a .NET 2.0.
Jörg W Mittag
@ Jörg, sí, hay un cambio. El DLR se reescribe en parte porque ahora la VM tiene soporte para la resolución dinámica.
Dykam
Era demasiado optimista, la investigación mostró que los cambios no fueron tan grandes.
Dykam
4
Un ejemplo de uso:
Consume muchas clases que tienen una propiedad comunitaria 'CreationDate':
publicclassContact{// some propertiespublicDateTimeCreationDate{get;set;}}publicclassCompany{// some propertiespublicDateTimeCreationDate{get;set;}}publicclassOpportunity{// some propertiespublicDateTimeCreationDate{get;set;}}
Si escribe un método commun que recupera el valor de la propiedad 'CreationDate', debería usar la reflexión:
Las víctimas de RAD y Python la usarán principalmente para destruir la calidad del código, IntelliSense y la detección de errores en tiempo de compilación.
Una respuesta cínica pero fácilmente demasiado cierta. Lo he visto simplemente para evitar declarar estructuras con el resultado de que el código funciona si todo está bien, pero vuela su pila de maneras impredecibles tan pronto como mueva su queso.
AnthonyVO
Sí, verás ese clásico corte de esquina con muchas otras características de lenguaje. No sorprende que también lo veas aquí.
Hawkeye4040
1
Se evalúa en tiempo de ejecución, por lo que puede cambiar el tipo como puede en JavaScript a lo que desee. Esto es legitimo:
dynamic i =12;
i ="text";
Y para que pueda cambiar el tipo que necesite. Úselo como último recurso; es beneficioso, pero escuché que muchas cosas pasan debajo de las escenas en términos de IL generada y eso puede tener un precio de rendimiento.
Dudaría en decir que es "legítimo". Seguramente compilará, por lo que es un "código legítimo" en el sentido de que el compilador ahora lo compilará y el tiempo de ejecución lo ejecutará. Pero nunca quisiera ver ese código en particular (o algo parecido) en ninguno de los códigos que mantengo, o sería un delito cercano.
Lasse V. Karlsen
66
Claro, pero eso habría sido "legítimo" con "objeto" en lugar de "dinámico". No has mostrado nada interesante sobre la dinámica aquí.
Eric Lippert
Para el objeto, tendría que convertirlo al tipo apropiado, para invocar cualquiera de sus métodos ... pierde la firma; puede hacer que su código llame a cualquier método sin error de compilación, y se produce un error en tiempo de ejecución. Tenía prisa por escribir, perdón por no especificar. Y @Lasse, estaría de acuerdo y probablemente no usaré mucho la dinámica.
Brian Mains
1
El caso de uso de último recurso no se explica
denfromufa
1
El mejor caso de uso de las variables de tipo 'dinámico' para mí fue cuando, recientemente, estaba escribiendo una capa de acceso a datos en ADO.NET ( usando SQLDataReader ) y el código invocaba los procedimientos almacenados heredados ya escritos. Hay cientos de esos procedimientos almacenados heredados que contienen la mayor parte de la lógica empresarial. Mi capa de acceso a datos necesitaba devolver algún tipo de datos estructurados a la capa de lógica de negocios, basada en C #, para hacer algunas manipulaciones ( aunque casi no hay ). Cada procedimiento almacenado devuelve un conjunto diferente de datos ( columnas de tabla ). Entonces, en lugar de crear docenas de clases o estructuras para contener los datos devueltos y pasarlos al BLL, escribí el siguiente código que se ve bastante elegante y ordenado.
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;}
Puede llamar a lenguajes dinámicos como CPython usando pythonnet:
dynamic np = Py.Import("numpy")
Puede emitir genéricos dynamical aplicar operadores numéricos en ellos. Esto proporciona seguridad de tipo y evita las limitaciones de los genéricos. Esto es en esencia * pato escribiendo:
Otro caso de uso para dynamicescribir es para métodos virtuales que experimentan un problema con covarianza o contravarianza. Un ejemplo de ello es el Clonemétodo infame que devuelve un objeto del mismo tipo que el objeto al que se llama. Este problema no se resuelve por completo con un retorno dinámico porque omite la comprobación de tipos estáticos, pero al menos no es necesario usar conversiones feas todo el tiempo según cuando se usa plain object. De lo contrario, los moldes se vuelven 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}}
Respuestas:
La palabra clave dinámica es nueva en C # 4.0 y se usa para decirle al compilador que el tipo de una variable puede cambiar o que no se conoce hasta el tiempo de ejecución. Piense en ello como si pudiera interactuar con un Objeto sin tener que lanzarlo.
Tenga en cuenta que no necesitamos emitir ni declarar al cliente como tipo Cliente. Debido a que lo declaramos dinámico, el tiempo de ejecución se hace cargo y luego busca y establece la propiedad FirstName para nosotros. Ahora, por supuesto, cuando está utilizando una variable dinámica, está renunciando a la verificación del tipo de compilador. Esto significa que la llamada cust.MissingMethod () se compilará y no fallará hasta el tiempo de ejecución. El resultado de esta operación es una RuntimeBinderException porque MissingMethod no está definido en la clase Customer.
El ejemplo anterior muestra cómo funciona la dinámica al llamar a métodos y propiedades. Otra característica poderosa (y potencialmente peligrosa) es poder reutilizar variables para diferentes tipos de datos. Estoy seguro de que los programadores de Python, Ruby y Perl pueden pensar en un millón de maneras de aprovechar esto, pero he estado usando C # tanto tiempo que me parece "incorrecto".
OK, lo más probable es que no escribas código como el anterior muy a menudo. Sin embargo, puede haber ocasiones en que la reutilización de variables pueda ser útil o limpiar una pieza sucia de código heredado. Un caso simple con el que me encuentro a menudo es tener que emitir constantemente entre decimal y doble.
La segunda línea no se compila porque 2.5 se escribe como doble y la línea 3 no se compila porque Math.Sqrt espera un doble. Obviamente, todo lo que tiene que hacer es emitir y / o cambiar su tipo de variable, pero puede haber situaciones en las que sea dinámico usarlo.
Leer más característica: http://www.codeproject.com/KB/cs/CSharp4Features.aspx
fuente
dynamic
in c # para resolver problemas que pueden resolverse (tal vez incluso mejor) mediante las características estándar de c # y la escritura estática, o como máximo con inferencia de tipos (var
).dynamic
debe solamente ser utilizado cuando se trata de cuestiones interoperabilty con el DLR. Si escribe código en un lenguaje tipado estático, como c # is, entonces hágalo y no emule un lenguaje dinámico. Eso es simplemente feo.dynamic
variables en su código donde no las necesita (como en su ejemplo con la raíz cuadrada), abandona la comprobación de errores de tiempo de compilación limpio; en cambio, ahora está recibiendo posibles errores de tiempo de ejecución.La
dynamic
palabra clave se agregó, junto con muchas otras características nuevas de C # 4.0, para que sea más fácil hablar con el código que vive o proviene de otros tiempos de ejecución, que tiene diferentes API.Toma un ejemplo.
Si tiene un objeto COM, como el
Word.Application
objeto, y desea abrir un documento, el método para hacerlo viene con no menos de 15 parámetros, la mayoría de los cuales son opcionales.Para llamar a este método, necesitaría algo como esto (estoy simplificando, este no es el código real):
Tenga en cuenta todos esos argumentos? Debe pasarlos ya que C # antes de la versión 4.0 no tenía una noción de argumentos opcionales. En C # 4.0, las API COM se han hecho más fáciles de trabajar al introducir:
ref
opcional para las API COMLa nueva sintaxis para la llamada anterior sería:
¿Ves cuánto más fácil se ve, cuánto más legible se vuelve?
Vamos a separar eso:
La magia es que el compilador de C # ahora inyectará el código necesario y trabajará con nuevas clases en el tiempo de ejecución, para hacer casi exactamente lo mismo que antes, pero la sintaxis se le ha ocultado, ahora puede concentrarse en el qué , y no tanto sobre cómo . A Anders Hejlsberg le gusta decir que tienes que invocar diferentes "encantamientos", que es una especie de juego de palabras con la magia de todo el asunto, en el que normalmente tienes que agitar las manos y decir algunas palabras mágicas en el orden correcto. para poner en marcha cierto tipo de hechizo. La antigua forma de API de hablar con objetos COM era mucho de eso, necesitabas saltar muchos aros para convencer al compilador de que compilara el código por ti.
Las cosas se descomponen en C # antes de la versión 4.0 aún más si intentas hablar con un objeto COM para el que no tienes una interfaz o clase, todo lo que tienes es una
IDispatch
referencia.Si no sabe qué es,
IDispatch
es básicamente un reflejo para los objetos COM. Con unaIDispatch
interfaz, puede preguntarle al objeto "cuál es el número de identificación del método conocido como Guardar", y construir matrices de cierto tipo que contengan los valores del argumento, y finalmente llamar a unInvoke
método en laIDispatch
interfaz para llamar al método, pasando todo la información que has logrado buscar juntos.El método Save anterior podría verse así (definitivamente este no es el código correcto):
Todo esto por solo abrir un documento.
VB tenía argumentos opcionales y soporte para la mayoría de esto fuera de la caja hace mucho tiempo, por lo que este código C #:
es básicamente solo C # ponerse al día con VB en términos de expresividad, pero hacerlo de la manera correcta, al hacerlo extensible, y no solo para COM. Por supuesto, esto también está disponible para VB.NET o cualquier otro lenguaje creado sobre el tiempo de ejecución de .NET.
Puede encontrar más información sobre la
IDispatch
interfaz en Wikipedia: IDispatch si desea leer más al respecto. Es realmente algo sangriento.Sin embargo, ¿qué pasaría si quisieras hablar con un objeto de Python? Hay una API diferente para la que se usa para los objetos COM, y dado que los objetos de Python también son de naturaleza dinámica, debe recurrir a la magia de reflexión para encontrar los métodos correctos para llamar, sus parámetros, etc. pero no el .NET Reflexión, algo escrito para Python, muy parecido al código IDispatch anterior, simplemente completamente diferente.
¿Y para Ruby? Una API diferente todavía.
JavaScript? Mismo trato, API diferente para eso también.
La palabra clave dinámica consta de dos cosas:
dynamic
dynamic
requiere la palabra clave y asigna las llamadas a la forma correcta de hacer las cosas. La API incluso está documentada, por lo que si tiene objetos que provienen de un tiempo de ejecución no cubierto, puede agregarlo.La
dynamic
palabra clave no está, sin embargo, la intención de reemplazar cualquier código .NET de sólo existente. Claro, puede hacerlo, pero no se agregó por esa razón, y los autores del lenguaje de programación C # con Anders Hejlsberg en el frente, han insistido firmemente en que todavía consideran que C # es un lenguaje fuertemente tipado y no sacrificarán ese principioEsto significa que aunque puede escribir código como este:
y compilarlo, no fue concebido como una especie de sistema de magia que permite descubrir qué querías decir en tiempo de ejecución.
Todo el propósito era facilitar el hablar con otros tipos de objetos.
Hay mucho material en Internet sobre la palabra clave, los proponentes, los opositores, las discusiones, las críticas, los elogios, etc.
Le sugiero que comience con los siguientes enlaces y luego busque en Google más:
fuente
dynamic
se agregó, para apoyar a otros ecosistemas sobre cómo se puede realizar la invocación de métodos de reflexión, así como proporcionar una especie de enfoque de recuadro negro a las estructuras de datos con una forma documentada de lograr esto.Me sorprende que nadie haya mencionado el envío múltiple . La forma habitual de evitar esto es a través del patrón de visitante y eso no siempre es posible, por lo que terminas con
is
cheques apilados .Así que aquí hay un ejemplo de la vida real de una aplicación propia. En lugar de hacer:
Tú lo haces:
Tenga en cuenta que en el primer caso
ElevationPoint
es una subclase deMapPoint
y si no se coloca antesMapPoint
, nunca será alcanzado. Este no es el caso con dinámico, ya que se llamará al método de coincidencia más cercano.Como puede adivinar por el código, esa característica fue útil mientras realizaba la traducción de objetos ChartItem a sus versiones serializables. No quería contaminar mi código con visitantes y tampoco quería contaminar mis
ChartItem
objetos con atributos específicos de serialización inútiles.fuente
is
apilado uno encima del otro.magic
; no hay tal cosa como magia.Facilita la interoperabilidad de los lenguajes de tipo estático (CLR) con los dinámicos (python, ruby ...) que se ejecutan en el DLR (tiempo de ejecución del lenguaje dinámico), consulte MSDN :
MSDN enumera estas ventajas:
Ver MSDN para más detalles.
fuente
Un ejemplo de uso:
Consume muchas clases que tienen una propiedad comunitaria 'CreationDate':
Si escribe un método commun que recupera el valor de la propiedad 'CreationDate', debería usar la reflexión:
Con el concepto 'dinámico', su código es mucho más elegante:
fuente
Interoperabilidad COM. Especialmente I Desconocido. Fue diseñado especialmente para ello.
fuente
Las víctimas de RAD y Python la usarán principalmente para destruir la calidad del código, IntelliSense y la detección de errores en tiempo de compilación.
fuente
Se evalúa en tiempo de ejecución, por lo que puede cambiar el tipo como puede en JavaScript a lo que desee. Esto es legitimo:
Y para que pueda cambiar el tipo que necesite. Úselo como último recurso; es beneficioso, pero escuché que muchas cosas pasan debajo de las escenas en términos de IL generada y eso puede tener un precio de rendimiento.
fuente
El mejor caso de uso de las variables de tipo 'dinámico' para mí fue cuando, recientemente, estaba escribiendo una capa de acceso a datos en ADO.NET ( usando SQLDataReader ) y el código invocaba los procedimientos almacenados heredados ya escritos. Hay cientos de esos procedimientos almacenados heredados que contienen la mayor parte de la lógica empresarial. Mi capa de acceso a datos necesitaba devolver algún tipo de datos estructurados a la capa de lógica de negocios, basada en C #, para hacer algunas manipulaciones ( aunque casi no hay ). Cada procedimiento almacenado devuelve un conjunto diferente de datos ( columnas de tabla ). Entonces, en lugar de crear docenas de clases o estructuras para contener los datos devueltos y pasarlos al BLL, escribí el siguiente código que se ve bastante elegante y ordenado.
fuente
dynamic np = Py.Import("numpy")
dynamic
al aplicar operadores numéricos en ellos. Esto proporciona seguridad de tipo y evita las limitaciones de los genéricos. Esto es en esencia * pato escribiendo:T y = x * (dynamic)x
, dóndetypeof(x) is T
fuente
Otro caso de uso para
dynamic
escribir es para métodos virtuales que experimentan un problema con covarianza o contravarianza. Un ejemplo de ello es elClone
método infame que devuelve un objeto del mismo tipo que el objeto al que se llama. Este problema no se resuelve por completo con un retorno dinámico porque omite la comprobación de tipos estáticos, pero al menos no es necesario usar conversiones feas todo el tiempo según cuando se usa plainobject
. De lo contrario, los moldes se vuelven implícitos.fuente