Pregunta

Solo trato de entender los genéricos leyendo este artículo esclarecedor de Juval Lowy

Parafraseando .. Cuando define una definición de clase genérica, se compila en IL.

  • Para los tipos de valor, tan pronto como solicite un tipo de valor específico, sustituye la T con su tipo de valor específico para obtener el IL para esa configuración específica, p. MyList<int> Beneficio: No hay sanciones de boxeo y desempaquetado.
  • Todo bien ... para los tipos de referencia, el compilador reemplaza todas las instancias de T en su definición con Object y crea el IL que se utiliza para todos los tipos de referencia. Sin embargo, las instancias se asignan según el tipo de referencia real solicitado, p. MyList<String>

Ahora pre-genéricos podríamos haber escrito métodos que toman Object parámetros. Generics afirma una mejora del rendimiento del 100% porque ' evita la penalización de rendimiento en la que incurres cuando rechazas el tipo de objeto a tu tipo específico cuando quieres usarlo'

 // assume GetItem returns an Object
 string sMyPreciousString = (string) obList.GetItem(); 

¿Cuál es este impacto en el rendimiento cuando baja de Object a un tipo de referencia específico? También parece que la conversión ascendente a Object (incluso los genéricos harían esto) no es un éxito en el rendimiento ... ¿por qué?

¿Fue útil?

Solución

La conversión al objeto no requiere una verificación del tiempo de ejecución: siempre funcionará, y es básicamente un no-op básicamente.

Downcasting requiere una verificación del tiempo de ejecución para asegurarse de que no está transmitiendo una transmisión a una cadena, por ejemplo. Es una penalización bastante pequeña, y es muy poco probable que sea un cuello de botella, pero evitarlo es solo un beneficio adicional para los genéricos.

Otros consejos

El impacto en el rendimiento proviene de la necesidad de una verificación de tipo de tiempo de ejecución. Si B es una subclase de A, entonces cuando conviertes una B en una A, sabes en tiempo de compilación que será seguro, ya que todos los Bs son As. Por lo tanto, no necesita generar ningún código de tiempo de ejecución para verificar el tipo.

Sin embargo, cuando echas una A en una B, no sabes en tiempo de compilación si la A es realmente una B o no. Podría ser solo una A, podría ser de tipo C, un subtipo diferente de A. Por lo tanto, debe generar un código de tiempo de ejecución que se asegurará de que el objeto sea realmente B y arroje una excepción si no lo es.

Los genéricos no tienen este problema, porque el compilador sabe, en el momento de la compilación, que solo B se colocaron en la estructura de datos, por lo que cuando extrae algo, el compilador sabe que será una B, por lo que no hay necesidad de la verificación de tipo en tiempo de ejecución.

Lectura sobre el IL que se genera (este artículo lo menciona). .. aha - isinst.

Si no estuviera abatido, no tendría que llamar a isinst .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top