Implicaciones de rendimiento de casting de C#



(2)

Cuando se utiliza la palabra clave 'como' en C # para hacer una conversión que falla, se devuelve null. ¿Qué está pasando en el fondo? ¿Simplemente está suprimiendo una excepción, así que no tengo que escribir el código de manejo para una falla?

Me interesan las características de rendimiento en comparación con un elenco típico envuelto en un try-catch.

https://src-bin.com


Answer #1

Se usa la instrucción IL para realizar el reparto en lugar de la instrucción de castclass que se usa al lanzar. Esta es una instrucción especial que realiza el lanzamiento si es válido, de lo contrario deja null en la pila si no lo es. Así que no, no solo suprime una excepción, y es órdenes de magnitud más rápido que hacerlo.

Tenga en cuenta que existen algunas diferencias de comportamiento entre la instrucción isinst y castclass , la principal es que isinst no tiene en cuenta los operadores de isinst definidos por el usuario, solo considera la jerarquía de herencia directa, por ejemplo, si define las siguientes dos clases sin herencia jerarquía, pero un operador de lanzamiento explícito:

class A
{
    public int Foo;
}

class B
{
    public int Foo;

    public static explicit operator B(A a)
    {
        return new B { Foo = a.Foo };
    }
}

Entonces, lo siguiente tendrá éxito:

var a = new A { Foo = 3 };
var b = (B)a;
Console.WriteLine(b.Foo); // prints 3

Sin embargo, no se compila lo siguiente, con el error 'No se puede convertir el tipo' A 'en' B 'a través de una conversión de referencia, conversión de boxeo, conversión de unboxing, conversión de envoltura o conversión de tipo nulo'

var a = new A { Foo = 3 };
var b = a as B;

Por lo tanto, si tiene una configuración de moldes definida por el usuario (que normalmente es una mala idea para los tipos de referencia, por esta razón y otras), entonces debe tener en cuenta esta diferencia.


Answer #2

Y para agregar a la excelente publicación de Greg ...

La primera vez que se hace referencia a un nuevo Tipo en tiempo de ejecución, el CLR carga en la memoria una estructura llamada COREINFO_CLASS_STRUCT (o algo similar) que contiene, entre otras cosas, un puntero al objeto COREINFO_CLASS_STRUCT para la clase base de la que proviene este objeto ... Esto crea efectivamente una lista vinculada de objetos COREINFO_CLASS_STRUCT para la cadena de herencia para el Tipo, que termina en COREINFO_CLASS_STRUCT para System.Object . Cuando ejecuta isinst , (o su método análogo es castclass ) simplemente tiene que encontrar la estructura de memoria COREINFO_CLASS_STRUCT para el tipo de concreto del objeto que está examinando, y recorrer esta lista vinculada para ver si el tipo al que está intentando enviar está en la lista.

También contiene un puntero a una matriz separada que contiene todas las interfaces implementadas por el Tipo, que debe buscarse por separado si está intentando enviar contenido a una interfaz.




c#  

c#