2009-01-27 10 views
71

Estoy tratando de entender cuando se produce la unión temprana/tardía en C#.Encuadernación temprana y tardía

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 utilizan la reflexión son un ejemplo de enlace tardío. Escribimos el código para lograr esto a diferencia del compilador. (Por ejemplo, llamar a 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 a los delegados y llamar a un método a través de una referencia de interfaz? ¿Es eso vinculante temprano o tardío?

Respuesta

89

Todo se enlaza temprano en C# a menos que vaya a través de la interfaz Reflection.

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 scripts usan el enlace tardío, y los lenguajes 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.

Encuadernació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 tenga 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.

Por lo tanto, hay una búsqueda que se produce para la función virtual. Esto está muy optimizado, por lo que sucederá muy rápidamente en el tiempo de ejecución.

temprana obligado

  • El compilador puede calcular dónde la función llamada será 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 compensado, por lo general hay comparaciones de texto que se harán.
  • La función de destino puede no existir.
  • La función de destino puede no aceptar los argumentos que se le pasaron, 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.
+0

Creo que quisiste decir "El lenguaje VB en sí no enlaza tarde ..." –

+0

En realidad, no uso VB ... así que no sé mucho sobre eso. Me refiero a C#, pero parece que solo me estaba repitiendo. Me imagino que estás en lo correcto, ¡así que lo arreglaré! –

+0

Con la palabra clave dinámica, la vinculación tardía estará disponible en C# 4. – configurator

16

C# 3 utiliza la unión temprana.

C# 4 agrega el enlace tardío con la palabra clave dynamic. Ver Chris Burrow's blog entry 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 al string.ToString(), el código C# está ligado 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.

+1

No estoy de acuerdo completamente con esta explicación. En C# marcando un método o campo de instancia como medio virtual, el tipo derivado puede anular la implementación del tipo base en la cadena de herencia. Con los métodos virtuales, el CLR sabe a qué método llamar en tiempo de ejecución en función de la instancia del objeto de tiempo de ejecución. Probablemente, la única parte con la que estoy de acuerdo es que es una implementación de polimorfismo. Entonces usted causa confusión al decir que no es vinculante tarde. Es un enlace tardío porque CLR solo puede llamar a la implementación correcta del tipo de tiempo de ejecución cuando conoce el tipo de tiempo de ejecución de la instancia del objeto. –

4

En la mayoría de los casos el primer enlace 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 usted no tiene el conocimiento de la clase en tiempo de compilación, entonces la única forma es unir finales utilizando la reflexión. Me he encontrado con un excelente video que explica estos conceptos: here's the link.

2

En términos muy simples, la vinculación anticipada ocurre en tiempo de compilación y el compilador conoce 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

http://www.youtube.com/playlist?list=PLAC325451207E3105

3

Su un post muy antiguo, pero quería añadir más información a la misma. 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.

3

pronto enlace

El propio nombre describe que el compilador sabe de 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:

cboItems ComboBox;

ListBox lstItems; En los ejemplos anteriores, si escribimos el cboItem y colocamos un punto seguido de, automáticamente poblará todos los métodos, eventos y propiedades de un cuadro combinado, porque el compilador ya sabe que es un cuadro combinado.

enlace en tiempo de

El propio nombre 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:

Objeto objItems;

objItems = CreateObject ("DLL o nombre del ensamblado"); Aquí durante el tiempo de compilación, no se determina el tipo de objItems. 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.

enlace anticipado versus tardía Encuadernación

Ahora que se acerca a la pictureâ € |

aplicación se ejecutará más rápido en el enlace temprano, ya que ningún boxeo o unboxing se hacen aquí.

más fácil de escribir el código de Enlace temprano, ya que el intellisense se rellena automáticamente

un mínimo de errores de enlace temprano, ya que la sintaxis se comprueba durante el mismo tiempo de compilación.

La vinculación tardía 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 mejoras futuras, si se utiliza la vinculación tardía.

El rendimiento será código en la vinculación anticipada. Ambos tienen ventajas y desventajas, es la decisión del desarrollador elegir el enlace apropiado según el escenario.

Cuestiones relacionadas