2010-05-22 11 views
64

¿Existe un equivalente para la palabra clave 'dynamic' C# 4 cuando se usa type VB.NET seguro, es decir, con Option Strict On?VB.NET equivalente para C# 'dynamic' con Option Strict On

+1

VB es seguro, ya sea que Option Strict esté activado o desactivado. Lea sobre el significado aquí http://msdn.microsoft.com/en-us/library/hbzz1a9a(VS.80).aspx –

+0

@jdk ok, supongo que tendré que estar de acuerdo. Sin embargo, me refiero a la seguridad del tipo revisado en tiempo de compilación, como habrás adivinado ... – jeroenh

+0

@jdk: la definición de seguridad de tipo que todos usan cuando se habla de lenguajes de programación es esta: http://en.wikipedia.org/wiki/Type_safety –

Respuesta

47

El equivalente es Object en VB.NET pero con Option Strict Off. Con Option Strict On no hay equivalente. Dicho de otra manera, la palabra clave dynamic brinda Option Strict Off funcionalidad equivalente a C#.

+5

Excepto que no es exactamente lo mismo. Por ejemplo, no pude encontrar la manera de invocar dinámicamente un método (vea http://stackoverflow.com/questions/17819977/dynamic-method-calling-in-vb-without-reflection) como lo hace en C#. – Pat

+5

Más al punto, el modelo C# le permite hacer una excepción para un objeto específico, el modelo VB lo obliga a hacerlo de forma mucho menos granular – Basic

+0

Sé que es una vieja pregunta, pero hay una forma de hacer el enlace y mantener la opción Estricto. Desde las propiedades del proyecto, pestaña Compilar, podemos establecer Enlace Tardío en "Ninguno" (y Opción Estricta tomar el estado "Personalizado") que permite hacer Enlace Tardío en un entorno más seguro que establecerlo en Desactivado – Sehnsucht

3

Puede activar Option Infer y Option Strict Off y aún tener algo muy cerca.

37

VB.NET siempre tenía incorporada la característica "dinámica", originalmente llamada vinculación tardía. Esta sintaxis fue apoyada por siempre:

Dim obj = new SomeComClass() 
obj.DoSomething() 

trabajado en código implementado en .NET y COM, siendo este último el uso más común. La palabra clave dinámica en C# le dio esa misma capacidad. Sin embargo, cambió en la versión 10 de VB.NET, ahora también está usando el DLR. Lo cual agrega soporte para enlaces dinámicos a implementaciones de lenguaje como Python y Ruby.

La sintaxis es exactamente la misma, use la palabra clave Dim sin As. Sin embargo, tendrá que usar Option Strict Off, Option Infer On puede suavizar ese golpe un poco. Muestra que C# usando una palabra clave específica para señalar el enlace dinámico fue una jugada bastante buena. Afaik todas las solicitudes para hacerlo en VB.NET también han sido consideradas pero no planeadas.

Si prefiere la Opción estricta activada entonces, usar la palabra clave Clase parcial para que pueda mover parte del código a otro archivo fuente es probablemente el enfoque más efectivo.

+12

@ Hans Passant: Sé que, sin embargo, la dinámica de C# no es lo mismo que la "vinculación tardía" de VB. En C#, con la palabra clave dinámica puedo ser muy explícito sobre las partes dinámicas de mi programa. Para mí es como decirle al compilador: "oye, sé lo que estoy haciendo para esta parte específica de mi programa". Con VB.Net tengo que desactivar Option Strict para todo mi proyecto, lo que puede provocar la aparición de errores sutiles. – jeroenh

+0

@Hans @jeroen. En su código editado, 'app' se deduce como tipo' Object', por lo que no es posible * usar * la aplicación de objetos de Excel 'app'. Por ejemplo, si sustituyo 'app.Calculate' donde tiene' REM etc ... 'no compila. Creo que este es el problema por el que Jeroen pregunta. El compilador dice 'Error 1 Option Strict On deshabilita el enlace tardío'. – MarkJ

+0

@MarkJ: tiene toda la razón. Revisé la especificación del lenguaje de la versión 10 de VB.NET para estar seguro. Sorprendentemente, el DLR no se menciona * en ningún lado *. Option Strict Off parece completamente inevitable. Mis disculpas por la pobre respuesta. –

1

Hay suficientes formas de manejar métodos y propiedades con objetos COM de vinculación tardía y tipo seguro (Option Strict On). Esto al usar los métodos Microsoft.VisualBasic.Interaction.CallByName y System.Type.InvokeMember. (O cree un archivo "parcial" separado donde Option Strict es Off).

Pero manejar eventos con enlace tardío de VB.NET no es tan sencillo como con el tipo dinámico en C#. Puede verificar el "truco" para eso en Dynamic Events in VB.NET.

6

Esto demostrará lo que Basic dice acerca de que VB no tiene la misma granularidad que C#. Tengo este pedazo de código en C#, que utiliza la reflexión para invocar dinámicamente un método en tiempo de ejecución:

var listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null); 

La razón por la que estoy haciendo esto es que "GetSomeData" podría ser cualquiera de una serie de métodos, cada uno recibiendo datos diferentes ¿Qué método invocar aquí depende de un parámetro de cadena pasado a este objeto en tiempo de ejecución, por lo que el valor de "GetSomeData" varía en tiempo de ejecución.

La firma del "GetSomeData" es:

public List<SomeResultSetClass> GetSomeData() 

Cada uno de los métodos invocados vuelve una especie de List<T> objeto. A continuación, voy a enviar el objeto listResult a un método genérico llamado de exportación, que se ve así:

void Export<T>(List<T> exportList, string filePath, byte fileType) where T: class; 

Aquí es donde nos encontramos con un problema. Invoke devuelve un objeto de tipo System.Object. Por supuesto, un List<T> también es un System.Object, pero la interfaz expuesta es el Sistema.Interfaz de objeto, no la interfaz IList. Si intento ejecutar el método Exportar, así:

myExportObj.Export(listResult, parms.filePath, parms.fileType); 

el código no se puede compilar. El error es:

The type arguments for method '...Export<T>...' cannot be inferred from the usage. Try specifying the type arguments explicitly.

No, gracias !! El problema es que el compilador no puede encontrar los metadatos IList, porque está mirando la interfaz System.Object. Ahora, puede crear un nuevo List<T>, asígnele (List<Whatever>) listResult, pero eso en primer lugar daña el propósito de la invocación dinámica.

La solución es cambiar var a dynamic:

dynamic listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null); 

Desde dinámica no pasa por la comprobación estática de tipos en tiempo de compilación, no nos un error de compilación. Luego, cuando el objeto dinámico pasa al método Export, el DLR (Dynamic Language Runtime) busca ver si puede convertir implícitamente el objeto para cumplir con los requisitos de la firma del método. Lo que por supuesto puede.

Ok, así es como funcionan las cosas en C#. Con VB, la línea es la siguiente:

Dim listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, Nothing) 

con Option Strict On, esta línea altera el compilador, como se esperaba. Sin eso, funciona bien. En otras palabras, en VB, tengo que desactivar el comprobador de tipos para todo el módulo que contiene la línea. No hay una granularidad más fina que eso.

0

Sí, ExpandoObject.

Dim dobj = Nueva System.Dynamic.ExpandoObject()

DObj.A = "abc"

DObj.B = 123

+1

El ExpandoObject parece utilizar un IDictionary (de cadena, objeto) bajo el capó. Interesante. – Brain2000

+0

La pregunta que se plantea es cómo hacerlo con 'Option Strict On'. Su respuesta solo funciona con 'Opción estricta desactivada' – Nick

0

Tenga en cuenta que incluso con la opción Estricto todavía puedes usar, por ejemplo un ExpandoObject para acceder a propiedades como:

Dim doc = JsonConvert.DeserializeObject(Of ExpandoObject)("{""name"":""Bob""}") 
Dim lookup as IDictionary(Of String, Object) = doc 
lookup("name") ' Bob 
Cuestiones relacionadas