Подтвердить что ты не робот

С# Эффективность литья

При использовании ключевого слова "как" в С#, чтобы сделать бросок, который не работает, возвращается null. Что происходит на заднем плане? Это просто подавление исключения, поэтому мне не нужно писать код обработки для отказа?

Меня интересуют характеристики производительности по сравнению с типичным литом, завернутым в try-catch.

4b9b3361

Ответ 1

Он использует инструкцию IL isinst для выполнения броска вместо castclass, которая используется при кастинге. Это специальная инструкция, которая выполняет листинг, если она действительна, иначе оставляет null в стеке, если это не так. Нет, это не просто подавляет исключение, а на порядок быстрее, чем это делает.

Обратите внимание, что существуют некоторые различия в поведении между инструкцией isinst и castclass - основная из них заключается в том, что isinst не учитывает пользовательские операторы приведения, она рассматривает только иерархию прямого наследования, например. если вы определяете следующие два класса без иерархии наследования, но явный оператор литья:

class A
{
    public int Foo;
}

class B
{
    public int Foo;

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

Тогда будет выполнено следующее:

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

Однако следующее не компилируется с ошибкой "Невозможно преобразовать тип" A "в" B "посредством преобразования ссылок, преобразования бокса, преобразования для распаковки, преобразования конверсий или преобразования нулевого типа"

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

Итак, если у вас есть настроенные пользователем настройки (которые обычно являются плохими идеями по ссылочным типам, по этой причине и другим), тогда вы должны знать об этой разнице.

Ответ 2

И добавить к Грегу отличный пост...

В первый раз, когда новый тип ссылается во время выполнения, CLR загружает в память структуру под названием COREINFO_CLASS_STRUCT (или что-то подобное), которая содержит, среди прочего, указатель на объект COREINFO_CLASS_STRUCT для базового класса, который этот объект происходит из... Это эффективно создает связанный список объектов COREINFO_CLASS_STRUCT для цепочки наследования для Типа, который заканчивается в COREINFO_CLASS_STRUCT для System.Object. Когда вы выполняете isinst (или аналогичный метод castclass), он просто должен найти структуру памяти COREINFO_CLASS_STRUCT для конкретного типа объекта, который вы изучаете, и пересечь этот связанный список, чтобы увидеть, является ли тип, который вы пытаясь включить в список.

Он также содержит указатель на отдельный массив, который содержит все интерфейсы, реализованные типом, которые необходимо искать отдельно, если вы пытаетесь применить к интерфейсу.