c# - Atascamiento temprano y tardío
binding late-binding (7)
Estoy tratando de entender cuando se produce la unión temprana / tardía en C #.
Los métodos no virtuales siempre se enlazan temprano. Los métodos virtuales siempre están vinculados de forma tardía: el compilador inserta un código adicional para resolver el método real al que se vincula en el momento de la ejecución y comprueba la seguridad del tipo. Entonces, el polimorfismo de subtipo usa unión tardía.
Los métodos de llamada que usan reflexión son un ejemplo de unión tardía. Escribimos el código para lograr esto a diferencia del compilador. (Por ejemplo, llamar a los componentes COM).
VB.NET admite el enlace implícito tardío cuando Option Strict está desactivado. Un objeto se enlaza tarde cuando se asigna a una variable declarada de tipo Objeto. El compilador de VB inserta el código para enlazar al método correcto en el momento de la ejecución y atrapar las llamadas no válidas. C # no es compatible con esta característica.
¿Estoy yendo en la dirección correcta?
¿Qué hay de llamar delegados y llamar a un método a través de una referencia de interfaz? ¿Es eso vinculante temprano o tardío?
C # 3 usa enlace temprano.
C # 4 agrega el enlace tardío con la palabra clave dynamic
. Ver la entrada del blog de Chris Burrow sobre el tema para más detalles.
En cuanto a los métodos virtuales frente a los no virtuales, este es un problema diferente. Si llamo a string.ToString()
, el código C # está vinculado al método virtual object.ToString()
. El código de la persona que llama no cambia en función del tipo de objeto. Por el contrario, los métodos virtuales se llaman a través de una tabla de indicadores de función. Una instancia de objeto se refiere a la tabla del objeto que apunta a su método ToString()
. Una instancia de cadena tiene su tabla de método virtual apuntando a su método ToString()
. Sí, esto es polimorfismo. pero no es vinculante tarde.
En la mayoría de los casos, la vinculación temprana es lo que hacemos a diario. Por ejemplo, si tenemos una clase Employee
disponible en tiempo de compilación, simplemente creamos la instancia de esa clase e invocamos a los miembros de la instancia. Esto es vinculante temprano.
//Early Binding
**Employee** employeeObject = new **Employee**();
employeeObject.CalculateSalary();
Por otro lado, si no tiene el conocimiento de la clase en el momento de la compilación, entonces la única forma es enlazar de forma tardía usando la reflexión. Me encontré con un excelente video que explica estos conceptos: aquí está el enlace .
En términos muy simples, la vinculación anticipada ocurre en tiempo de compilación y el compilador tiene el conocimiento sobre el tipo y todos sus miembros, y la vinculación tardía ocurre en tiempo de ejecución, el compilador no sabe nada sobre el tipo y sus miembros. Me encontré con un video excelente en youtube que explica estos conceptos.
http://www.youtube.com/watch?v=s0eIgl5iqqQ&list=PLAC325451207E3105&index=55&feature=plpp_video
Enlace temprano
El nombre en sí mismo describe que el compilador sabe qué tipo de objeto es, cuáles son todos los métodos y propiedades que contiene. Tan pronto como haya declarado el objeto, .NET Intellisense completará sus métodos y propiedades al hacer clic en el botón de puntos.
Ejemplos comunes:
ComboBox cboItems;
ListBox lstItems; En los ejemplos anteriores, si escribimos el cboItem y colocamos un punto seguido de, automáticamente se rellenarán todos los métodos, eventos y propiedades de un cuadro combinado, porque el compilador ya sabe que es un cuadro combinado.
Enlace tardío
El nombre en sí mismo describe que el compilador no sabe qué tipo de objeto es, cuáles son todos los métodos y propiedades que contiene. Tienes que declararlo como un objeto, luego necesitas obtener el tipo del objeto, los métodos que están almacenados en él. Todo se conocerá en el tiempo de ejecución.
Ejemplos comunes:
ObjItems del objeto;
objItems = CreateObject ("DLL o nombre del ensamblado"); Aquí durante el tiempo de compilación, el tipo de objItems no está determinado. Estamos creando un objeto de un dll y asignándolo a los objItems, por lo que todo se determina en el tiempo de ejecución.
Unión temprana versus unión tardía
Ahora entrando en la imagen ...
La aplicación se ejecutará más rápido en el enlace anticipado, ya que aquí no se realiza el boxeo ni el desempaquetado.
Es más fácil escribir el código en Early binding, ya que el intellisense se completará automáticamente
Errores mínimos en el enlace anticipado, ya que la sintaxis se comprueba durante el tiempo de compilación en sí.
El enlace tardío sería compatible con todo tipo de versiones, ya que todo se decide en el tiempo de ejecución.
Impacto mínimo del código en las mejoras futuras, si se utiliza la vinculación tardía.
El rendimiento será código en el enlace anticipado. Ambos tienen méritos y deméritos, es la decisión del desarrollador elegir el enlace apropiado según el escenario.
Es una publicación muy antigua pero quería agregarle más información. La vinculación tardía se utiliza cuando no desea crear una instancia del objeto en tiempo de compilación. En C#
, usa Activator
para llamar al objeto bind en el tiempo de ejecución.
Este artículo es una guía para construir un componente .NET, usándolo en un proyecto Vb6 en tiempo de ejecución utilizando el enlace tardío, adjuntando sus eventos y obteniendo una devolución de llamada.
http://www.codeproject.com/KB/cs/csapivb6callback2.aspx
Este artículo es una guía para construir un componente .NET y usarlo en un proyecto VB6. Hay muchas muestras sobre este tema, entonces, ¿por qué escribí una nueva? En mi humilde opinión, en otros artículos, la parte faltante es adjuntar su evento en tiempo de ejecución. Por lo tanto, en este artículo, crearemos un componente .NET, lo marcaremos como un componente COM visible, lo utilizaremos en tiempo de ejecución en VB6 y lo conectaremos a sus eventos.
https://www.codeproject.com/Articles/37127/Internet-Explorer-Late-Binding-Automation
La mayoría de los desarrolladores a menudo necesitan la automatización de Internet Explorer, lo que básicamente significa abrir un navegador, rellenar algunos formularios y publicar datos mediante programación.
El enfoque más común es usar shdocvw.dll (el control del navegador web de Microsoft) y Mshtml.dll (el componente de análisis y representación HTML), o Microsoft.Mshtml.dll que en realidad es un contenedor .NET para Mshtml.dll. Puede obtener más información sobre Internet Explorer - Acerca del navegador aquí.
Si elige el método y las DLL anteriores, veamos algunos de los problemas que puede tener que enfrentar:
Debe distribuir estos archivos DLL porque su proyecto dependería de estos archivos DLL, y este es un problema grave si no puede implementarlos correctamente. Simplemente busque en Google sobre los problemas de distribución de shdocvw y mshtml.dll, y verá de lo que estoy hablando. Debe implementar un archivo Microsoft.mshtml.dll de 8 MB porque este archivo DLL no forma parte de .NET Framework. En este caso, lo que tenemos que hacer es usar una técnica de unión tardía. Escribir nuestros propios contenedores para los archivos DLL mencionados anteriormente. Y, por supuesto, haremos esto ya que es más útil que usar estos archivos DLL. Por ejemplo, no necesitaremos verificar si la operación de descarga del documento está completa porque IEHelper lo hará por nosotros.
Todo se enlaza temprano en C # a menos que vaya a través de la interfaz de reflexión.
El límite inicial solo significa que el método de destino se encuentra en tiempo de compilación, y se crea un código que lo llamará. Ya sea virtual o no (lo que significa que hay un paso adicional para encontrarlo en el momento de la llamada es irrelevante). Si el método no existe, el compilador no compilará el código.
Límite tardío significa que el método de destino se busca en el tiempo de ejecución. A menudo, el nombre textual del método se usa para buscarlo. Si el método no está allí, bang. El programa se bloqueará o entrará en algún esquema de manejo de excepciones en tiempo de ejecución.
La mayoría de los lenguajes de script utilizan el enlace tardío y los idiomas compilados usan el enlace anticipado.
C # (anterior a la versión 4) no se une tarde; sin embargo, pueden usar la API de reflexión para hacerlo. Esa API compila un código que busca nombres de funciones al explorar ensamblajes en tiempo de ejecución. VB puede enlazarse tarde si Option Strict está desactivado.
La unión generalmente tiene un efecto en el rendimiento. Debido a que el enlace tardío requiere búsquedas en el tiempo de ejecución, por lo general significa que las llamadas a métodos son más lentas que las llamadas a métodos enlazados.
Para una función normal, el compilador puede calcular su ubicación numérica en la memoria. Luego, cuando se llama a la función, puede generar una instrucción para llamar a la función en esta dirección.
Para un objeto que tiene algún método virtual, el compilador generará una tabla v. Esto es esencialmente una matriz que contiene las direcciones de los métodos virtuales. Cada objeto que tiene un método virtual contendrá un miembro oculto generado por el compilador que es la dirección de la tabla v. Cuando se llama a una función virtual, el compilador determinará cuál es la posición del método apropiado en la tabla v. Generará código para buscar en la tabla v de los objetos y llamará al método virtual en esta posición.
Entonces, hay una búsqueda que ocurre para la función virtual. Esto está muy optimizado, por lo que sucederá muy rápidamente en el tiempo de ejecución.
Límite temprano
- El compilador puede determinar dónde estará la función llamada en tiempo de compilación.
- El compilador puede garantizar anticipadamente (antes de que se ejecute el código de cualquier programa) que la función existirá y se podrá llamar en el tiempo de ejecución.
- El compilador garantiza que la función toma el número correcto de argumentos y que son del tipo correcto. También verifica que el valor de retorno sea del tipo correcto.
Enlace tardío
- La búsqueda llevará más tiempo porque no es un simple cálculo de compensación, generalmente hay que hacer comparaciones de texto.
- La función objetivo puede no existir.
- La función de destino puede no aceptar los argumentos que se le pasan y puede tener un valor de retorno del tipo incorrecto.
- Con algunas implementaciones, el método de destino realmente puede cambiar en tiempo de ejecución. Entonces, la búsqueda puede ejecutar una función diferente. Creo que esto sucede en el lenguaje de Ruby, puede definir un nuevo método en un objeto mientras el programa se está ejecutando. La vinculación tardía permite que las llamadas a funciones comiencen a invocar una nueva anulación para un método en lugar de llamar al método base existente.