2010-05-06 2 views
3

Когда вы делаете upcast или downcast, что действительно происходит за кулисами? У меня была мысль, что когда что-то делать, как:Как действительно кастинги работают на уровне CLR?

string myString = "abc"; 
object myObject = myString; 
string myStringBack = (string)myObject; 

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

.maxstack 1 
.locals init (
    [0] string myString, 
    [1] object myObject, 
    [2] string myStringBack) 
L_0000: nop 
L_0001: ldstr "abc" 
L_0006: stloc.0 
L_0007: ldloc.0 
L_0008: stloc.1 
L_0009: ldloc.1 
L_000a: castclass string 
L_000f: stloc.2 
L_0010: ret 

Почему CLR нужно что-то вроде castclass string?

Есть два возможных реализаций для потупив:

  1. Вам требуется castclass something. Когда вы добираетесь до строки кода, которая делает castclass, CLR пытается сделать трансляцию. Но тогда, что произойдет, если бы я отказался от строки строки castclass и попытался запустить код?
  2. Вам не требуется castclass. Поскольку все ссылочные типы имеют схожую внутреннюю структуру, если вы пытаетесь использовать строку в экземпляре формы, она будет исключать неправильное использование (поскольку она определяет, что форма не является строкой или каким-либо ее подтипом).

Кроме того, является ли следующий statamente из C# 4.0 в двух словах правильным?

Upcasting and downcasting between compatible reference types performs reference 
conversions: a new reference is created that points to the same object. 

Действительно ли это создает новую ссылку? Я думал, что это будет одна и та же ссылка, только в другом типе переменной.

Thanks

ответ

11

У меня возникла мысль, что на самом коде не будет внедрен код в самом коде.

Интересная идея. Как вы думали, что это сработало?

try 
{ 
    object x = 123; 
    object y = (string)x; 
} 
catch(InvalidCastException ex) 
{ ... } 

Если бросок не производит никакого кода, то где же код, который бросает исключение произойдет?

Помните, Основной целью из отлитых из менее определенного типа для более конкретного типа для выполнить проверку типа во время выполнения.

Как только проверка типа проходит, то обязательно, ничего больше не должно произойти. Биты ссылки перед проверкой типа и битами после проверки типа являются одинаковыми битами; мы только что проверили, что новое использование старых бит оправдано.

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

Где это обнаружено? Я имею в виду, что в точно какая команда обнаружена? В инструкции castclass. Для этого и предназначена команда castclass.

Что произойдет, если бы я пропустил строчку строки castclass и попытался запустить код?

Тип проверки безопасности отклонил вашу программу. Если бы вы вынудили CLR запустить его без прохождения проверки, тогда у него было бы неопределенное поведение. Возможно, он преуспел, возможно, он провалился, он, возможно, отформатировал ваш жесткий диск.

Действительно ли это создает новую ссылку?

Помните, что на уровне реализации ссылка представляет собой просто целое число указателя. Это номер, который менеджер памяти может использовать для отслеживания позиции указанных данных. Это может быть указатель, это может быть ручка, неважно, что это такое; это то, что реализует абстрактное понятие ссылки.

Когда у вас есть переменная, содержащая 12, и вы «замените» ее содержимое на 12, является ли это «новым» 12, который только что был создан или это «старый» 12? Предположим, вы сделали вторую переменную и поместили 12 в нее, скопировав ее из первой переменной. Это «новый» 12 или «старый» 12? Как вы можете сказать? Это разница, которая не имеет значения. Когда вы создаете «новую» ссылку, идентичную «старой» ссылке, это создание чего-то нового? Вопрос - философский вопрос, а не технический.

+0

Эрик, вероятно, ортогональный вопрос. Но как CastClass сравнивается с методом вывода типа GetType()? Оба, похоже, принадлежат к System.Reflection. Я спрашиваю, потому что в тех случаях, когда мне нужно проверить совместимость типа времени выполнения (например, переопределить Equals), было бы быстрее выполнить его или сделать GetType == other.GetType()? – Kakira

+0

@Kakira: Это сайт вопросов и ответов. Я рекомендую вам разместить свой вопрос как вопрос, а не как комментарий! Однако, если ваш вопрос имеет форму «какая из этих двух вещей быстрее?» то не беспокойтесь, чтобы задать вопрос. Напишите код в обоих направлениях, запустите его в обоих направлениях, а затем вы узнаете, что быстрее. –

+0

Приношу свои извинения, и я вижу вашу точку зрения. Я проверю это. Просто интересовался внутренней работой CLR, но, похоже, не смог найти все это в одном месте :). – Kakira

4

Вы вводите в заблуждение ссылку с экземпляром. Создана новая ссылка, а не новый экземпляр.

object foo = "bar"; 
string baz = (string)foo; 

Новая ссылка к строке "foo" присваивается переменной baz (но есть еще только один экземпляр строки, это просто, что обе переменные указывают на один экземпляр). Если бы это не так, у вас было бы нечто похожее на тип «рукоятки». Если baz и foo были буквально та же ссылка, то это ..

foo = "bim"; 

бы также сделать baz равным "bim" (также, назначая тип нестроковой бы baz больше не указывают на действительной справки строки).

Вы можете выполнить бросок на ссылочном типе, если они находятся в одной и той же наследственной иерархии (один наследуется от другого прямо или косвенно) или когда существует явное преобразование между типами. Обратите внимание, что явные преобразования, как и все другие операторы, не являются полиморфными, т. Е. Преобразование должно быть определено конкретно на одном из рассматриваемых классов, а не в другом месте иерархии.

Явное преобразование, если оно присутствует, будет иметь приоритет, даже если соответствующие типы совместимы без него.В случае явного преобразования у вас нет гарантии (на самом деле, это маловероятно), что результат преобразования/преобразования будет указывать на тот же экземпляр, что и объект.

+0

а как насчет объекта obj = "abc"; string strA = "ничего"; strA = obj ;. Будет ли это создавать новую ссылку на последней строке? Или значение ссылки изменится с адреса «ничего» на адрес «abc»? –

+0

@devoured: Код, который вы указали, не будет компилироваться, поскольку downcasting должен быть явным. 'obj = strA' будет компилироваться, но да, это изменит' obj' на указание на '' abc "' на указание на '' nothing ''. Это другая ссылка с одинаковым значением. Подумайте об этом как о различии между параметрами «ref» и нормальными параметрами. –

Смежные вопросы