Преобразование типов с#

228
09 апреля 2017, 00:03

Объясните почему возникает ошибка на этапе выполнения?

namespace CSharp
{
internal class B  {  }
internal class D : B { }
internal class Program
{
    private static void Main()
    {
        Object o1 = new Object();
        B b1 = new B();
        D d6 = (D)b1; //System.InvalidCastException - не удалось привести тип объекта "CSharp.B" к типу "CSharp.D"
        B b5 = (B)o1; //System.InvalidCastException - не удалось привести тип объекта "CSharp.Object" к типу "CSharp.B"
    }
}
}
Answer 1

Все просто, переменная b1 ссылается на объект типа B. Тип B в свою очередь является базовым для типа D, т.е. D является производным от B. Привести объект базового типа к более производному нельзя.

D d6 = (D)b1; 

Аналогичная проблема и с этой строчкой

B b5 = (B)o1;

P.S. Небольшое замечание, если мы напишем следующий код:

B b = new D();
D d = (D)b;

и попробуем его выполнить, ошибки не будет. Здесь важно понимать следующее, что несмотря на то, что переменная b у нас типа B, она ссылается на объект типа D, поэтому приведение к типу D сработает. Т.е. строчка ниже выполнится без проблем.

D d = (D)b; // все ОК
Answer 2

Внимательно читаем комментарии в коде

namespace CSharp
{
    //не смотря на отсутствие явного указания B является производным от Object
    internal class B  {  }
    //класс D является производным от B и как следствие от Object
    internal class D : B { }
    internal class Program
    {
        private static void Main()
        {
            //все варианты ниже допустимы т.к. любой класс наследуется от Object
            Object o1 = new Object();//создаем базовый объект типа Object
            //ниже используется неявное приведение типов
            Object o2 = new B();//создаем объект типа B в переменной типа Object
            Object o3 = new D();//создаем объект типа D в переменной типа Object

Иными словами, если класс B является наследником класса A, то B является частным случаем A, и обладает всеми особенностями A плюс собственные особенности.

            //допустимо
            B b1 = new B();
            B b2 = new D();//D является производным от B
            //недопустимо
            B b3 = new Object();//Object не обладает всеми особенностями B

Явное приведение типов позволяет выбрать какой интерфейс объекта использовать, но не выполняет модификацию самого объекта.

            //Допустимо
            B b4 = (B)o2; //в переменной o2 лежит объект типа B, меняем используемый интерфейс
            B b5 = (B)o3; //в переменной o3 лежит объект типа D, меняем используемый интерфейс
            D d1 = (D)o3; //в переменной o3 лежит объект типа D, меняем используемый интерфейс
            D d2 = (D)b2; //в переменной b2 лежит объект типа D, меняем используемый интерфейс
            //не допустимо
            B b6 = (B)o1; //Object не обладает всеми особенностями B
            D d3 = (D)o1; //Object не обладает всеми особенностями D
            D d4 = (D)o2; //B не обладает всеми особенностями D
            D d5 = (D)b1; //B не обладает всеми особенностями D
        }
    }
}
READ ALSO
Быстро сравнить N папок между собой

Быстро сравнить N папок между собой

Допустим имеется 2 шары и нужно удостоверится, что они идентичны друг другу

229
Как в double записать число 0.50, а не 0.5?

Как в double записать число 0.50, а не 0.5?

Как в double записать число 050, а не 0

227
Перечислениe enum Keys для сочетания клавиш

Перечислениe enum Keys для сочетания клавиш

приветствуюпишу в WForms маленькую утилиту под windows , которая расширяет возможности буфера копирования

233
Аналог JSON_NUMERIC_CHECK

Аналог JSON_NUMERIC_CHECK

Подскажите пожалуйста, есть ли какой-нибудь аналог вот такой команды:

240