Рассмотрим этот сценарий:
// This decides what derived class to return depending on parameters you pass in
FunkyBase funky = FunkyFactory.Create("A");
Если компилятор выполнил некоторый анализ, чтобы определить, что funky
всегда FunkyDerivedA
в зависимости от того, что вы передаете, то два фрагмента кода тесно связаны.Этот код говорит: «Я знаю, что это FunkyBase
или что-то производное от него, , но это все, что я знаю , поэтому не давайте мне никаких опций, которые не входят в этот базовый класс».Если Visual Studio и компилятор .NET предоставят вам все методы и свойства для FunkyDerivedA
, то вы можете сделать это:
public class FunkyDerivedA : FunkyBase
{
public SomeProperty { get; set; }
}
///// SNIP /////
FunkyBase funky = FunkyFactory.Create("A");
funky.SomeProperty = 7;
И тогда все работает, потому что это фактический объект, который вы используете.Но в один прекрасный день что-то меняется, и вы хотите переключиться на FunkyDerivedB
, забыв, что это свойство не существует в этом классе.
public class FunkyDerivedA : FunkyBase
{
public SomeProperty { get; set; }
}
// notice it doesn't have the same property
public class FunkyDerivedB : FunkyBase
{
}
///// SNIP /////
// Danger, Will Robinson!
FunkyBase funky = FunkyFactory.Create("B");
funky.SomeProperty = 7;
В этот момент вещи могут потерпеть неудачу совершенно неочевидными способами.,Кастинг - это ваш сигнал, что вы знаете, что делаете.Это напоминание вам или любому, кто поддерживает ваш код, что вы делаете предположения о типе объекта, который вы получаете (в данном случае из фабричного метода), и следует соблюдать осторожность при изменении этого кода.
Это не значит, что C # не может делать то, что вы просите.Это может в некоторой степени.
В .NET v3.0 ключевое слово var
(см. статью MSDN ) позволяет отказаться от объявления типа:
var funky = new FunkyDerivedA();
Проверка типов Intellisense и времени компиляции, она просто выясняет, какой тип основан на типе возвращаемого значения метода.Обратите внимание, что в приведенном выше примере с фабрикой, если метод Create
просто возвращает базовый класс, это будет тип.Он не приведёт его к более производному классу, основанному на анализе дерева вызовов или чего-либо подобного.
В .NET v4.0 вы можете использовать dynamic
(см. MSDNКлючевое слово article ), которое прекращает проверку типов во время компиляции, позволяя вам делать то, что вы хотите.Конечно, если вы ошибетесь, вы получите исключение времени выполнения (не ошибка времени компиляции), поскольку оно разрешается во время выполнения, а не во время компиляции.Точно так же Intellisense не работает, поэтому вам необходимо убедиться, что вы знаете, что это за объект и какие члены доступны.
Также обратите внимание, что, как и при кастинге, ключевое слово dynamic
также является сигналом того, что вы знаете, что делаете, и несете ответственность за все, что не правильно.
Надеюсь, это поможет