В C # мне когда-либо приходилось выполнять явное восходящее преобразование?

Учитывая иерархию классов с базовым классом B и подклассом S:

class B { }
class S : B { }

Я могу присвоить S B с неявным преобразованием:

B b = new S();

Если бы я хотел понизить это обратно до S, мне пришлось бы сделать это явно:

B b = new S();
...
S s = (S)b;

Теперь, насколько я понимаю, мы можем гарантировать, что совместимость присваивания всегда будет идти от S к B, поэтому нам никогда не придется выполнять явное преобразование вверх следующим образом:

S s = new S();
B b = (B)s; // or
B b2 = s as B;

Верно ли это утверждение, или, как говорится в вопросе, нужно ли мне когда-либо выполнять явное повышение?


person James Wiseman    schedule 25.10.2012    source источник
comment
Если вы намеренно преобразуете объекты в любом месте своей кодовой базы, я думаю, вы нарушите принцип подстановки Лискова по определению.   -  person MarioDS    schedule 26.10.2017


Ответы (2)


Если у вас есть

class B { }
class S : B { }
class T : B { }

и вы пытаетесь сделать что-то вроде

var b = myBool ? new S() : new T();

это не скомпилируется, если вы явно не приведете экземпляр S или T (или оба) к B.

То же самое касается анонимных методов; это

new bool[0].Select(b => 
    { if (b) { return new S(); } else { return new T(); } });

не будет компилироваться без приведения типов (или указания Select<bool, B>, но это может быть невозможно, например, если ваш источник является анонимным типом).

Кроме того, если у вас есть

class B { public void DoSomething() { } }
class S : B { public new void DoSomething() { } }

тогда

S s = new S();
s.DoSomething();       // calls the S version
((B)s).DoSomething();  // calls the B version
person Rawling    schedule 25.10.2012
comment
Я не уверен в вызове базовой версии с приведением, я думал, что это может быть так, но пошел исследовать, и это похоже, что это не так - person James Barrass; 25.10.2012
comment
@JamesB Это не работает для виртуальных методов, но работает для методов, скрытых new. - person Rawling; 25.10.2012
comment
Принятый! За то, что послал меня на интересный тагент. - person James Wiseman; 25.10.2012

Вы можете использовать интерфейсы, если класс имеет явную реализацию:

interface I {
    void Method();
}

class C : I {
    void I.Method() { ... }
}

C c = new C();
c.Method();      // won't compile
((I)c).Method(); // have to cast to I first
person thecoop    schedule 25.10.2012