2013-12-17 2 views
1

Вот код:понижающее приведение безопасности

Base b = new Derived(); // Upcasting 
// Some actions 
Derived d = (Derived)b; // Downcasting 

Как я понимаю, речь идет как трафарет, через который вы смотрите на какой-то кусок памяти. И повышение уровня просто сужает этот трафарет, поэтому вы не можете получить доступ к членам, добавленным в класс Derived. И Downcasting здесь расширяет этот трафарет назад.

Вопрос: Поскольку никакая ссылка на производную часть типа не сохранилась, просто база. Может случиться так, что некоторые действия или активность GC стирают или перезаписывают кусок памяти, который использовался, чтобы содержать члены Derived, к тому времени, когда произошло понижение? Другими словами, может понизиться Derived d = (Derived)b?

+0

Это может быть, но только если 'b' не' Derived'. – Tony

+0

Спасибо, я это знаю. Но может ли потерянная часть типа быть потеряна, поскольку никакая ссылка на нее не сохранила только базовую. –

ответ

1

Это безопасный листинг в контексте. Вы создали Derived экземпляр , поэтому всегда можно лечить Производные как производные; нет GC деятельность может испортить часть экземпляра. Casting является своего рода лечения (я буду относиться к реальноDerived istance как Base только: Я обещал позвонить только подмножество методов, свойств) и литья себе является всегда безопасно.

// Actual instance is derived, but I'm going to restrict 
    // my work with them: I've promissed not to call for "b" 
    // any derived methods/properties 
    Base b = new Derived(); 

    // What is the actual type of "b"? 
    String typeName = b.GetType().Name; // <- "Derived" 

    // Try to convert to Derived 
    // This's better way to cast then (Derived) b 
    Derived d = b as Derived; 

    // Since "b" is actually Derived d will ne not null 
    if (Object.RefrenceEquals(null, d)) { 
    Console.Write("b is Derived"); 
    } 

    // You can also check 
    if (b is Derived) { 
    Console.Write("b is a Derived instance."); 
    } 
+0

Это тот ответ, который я искал. Большое спасибо! –

2

Эта переменная указывает на место памяти, в котором находится фактический объект. Если вы создали объект типа Derived, переменная указывает на ячейку памяти, где находится экземпляр этого типа. Даже если вы используете базовый тип Base, экземпляр в памяти имеет тип, который вы создали. Таким образом, downcast не может потерпеть неудачу, если вы уверены, что b имеет тип Derived.

0

Нет, он не может потерять информацию. Тем не менее, приведение может потерпеть неудачу, если эта информация никогда не была в первую очередь. Если b никогда не принадлежал к типу Derived или производному типу, он генерирует исключение.

Base b = new b(); 
// Some actions 
Derived d = (Derived)b; // will fail, b never was of type Derived. 
0

1) по времени «GC сотрет ... в блок памяти», что хранение б, код «= (производный) б» б больше не находится в памяти, конечно, не удалось , но GC не должен стирать его, если вы не играете со слабыми ссылками.

2) Основание b = новое Производные(); Я не понимаю, почему вы хотите сделать это «оживление». ваш код уже имеет сильную ссылку/тип производного, может также использоваться Derived b = ....

+0

1) Не все b - но только члены, которые Derived добавляет к базе так долго, что мы имеем переменную, ссылающуюся только на базовую часть. 2) Вопрос не практический, но теоретический. :) –

+0

, когда вы создаете b как Производный, все члены/реквизит хранятся в памяти. тип Base работает так же, как маска/кастинг, но под ним фактически есть Derived. – Kelmen

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