The_Unknown_Member Ответов: 2

C# что именно выполняется во время выполнения, когда я выполняю явное приведение?


Я всегда думал, что явное приведение-это просто способ сказать компилятору, что я знаю, что делаю, когда это не так
Например:
static void Main()
       {
           object blabla = new Derived();
           AcceptABase(blabla); /* This call to the method won't work because the compiler sees that I have an object variable that points to something that will be evaluated at runtime (in this case a reference to a derived object) so it can't guarantee that this code will execute (because System.Object is more general than Base) so I have to tell it that I know what I'm doing

       }

       static void AcceptABase(Base b)
       {
       }


но я читал в книге по C# и .NET, что явное приведение выполняется во время выполнения. Я действительно запутался. Что на самом деле происходит во время выполнения кастинга? Меняет ли он тип (и какой именно)?

Что я уже пробовал:

Ну, мой вопрос на самом деле не является реальной проблемой программирования, а просто вопросом о явном кастинге.

2 Ответов

Рейтинг:
8

Dave Kreskowiak

Это не меняет тип экземпляра. Приведение просто означает "Я собираюсь рассматривать этот экземпляр как этот тип", но это работает только в том случае, если тип, к которому вы его приводите, находится где-то в дереве наследования экземпляра. Ну, где-то выше исходного типа экземпляров.

Итак, предположим, что у вас есть следующее дерево наследования:

System.Object
  MyNamespace.MyBaseClass
    MyNamespace.MyFirstInheritedClass
      MyNamespace.MySecondInheritedClass
        MyNamespace.MyThirdInheritedClass

и вы создаете экземпляр MySecondInheritedClass, вы можете привести его к любому типу выше типа, который вы создали, MyFirstInheritedClass, MyBaseClass или Object. Это происходит потому, что MySecondInheritedClass реализует все в каждом типе в дереве наследования и выше него.

Вы не можете бросить его вниз по дереву, то есть вы не можете бросить его в MyThirdInheritedClass. Это происходит потому, что тип MySecondInheritedClass не реализует ничего, что MyThirdInheritedClass добавил к типу MySecondInheritedClass.

Опять же, когда вы говорите "приведение", явное или неявное, вы просто говорите: "Я буду относиться к этому экземпляру так, как если бы это был этот тип". Когда это происходит, вы получаете доступ только к методам и свойствам этого нового типа, даже если вы передаете этот экземпляр приведения другому методу.


Maciej Los

5ed!

Рейтинг:
18

OriginalGriff

Любое приведение - неявное или явное - изменяет тип объекта: но на самом деле оно не изменяет объект вообще, оно просто проверяет, что объект имеет тип, подходящий для приведения, и что такая операция приведения существует.

Например, существуют явные операторы приведения для int в decimal, double в float, float в byte, byte в integer и т. д. Также можно привести вверх или вниз дерево наследования:

class A {}
class B : A {}
class C : B {}
class D : A {}

Все это будет работать:
A a = new C();
B b = (C) a;
C c = (C) a;
Это будет компилироваться, но завершится неудачей во время выполнения:
D d = (D) a;
потому что, хотя D является производным от A и таким же образом является C, вы не можете привести экземпляр C к классу D, потому что нет прямого вывода и нет явного оператора приведения.
Он компилируется, потому что D является производным от A, поэтому переменная A может содержать экземпляр D, но потерпит неудачу во время выполнения, если это не так.

Так что да, приведение выполняется во время выполнения, но на самом деле ничего не меняется - система просто проверяет, что это законное приведение, которое она не может сделать во время компиляции.


Maciej Los

5ed!