Преобразование базового класса в производный класс
Можно ли в С# явно преобразовать объект базового класса в один из его производных классов? В настоящее время я думаю, что мне нужно создать конструктор для моих производных классов, которые принимают объект базового класса в качестве параметра и копируют значения свойств. Мне не очень нравится эта идея, поэтому я хотел бы избежать ее, если это возможно.
Это не похоже, что он должен работать (объект создается как новая база, поэтому память не должна выделяться для дополнительных членов производного класса), но С#, похоже, позволяет мне это сделать:
class BaseClass
{
... some stuff ...
}
class DerivedClass : BaseClass
{
public bool MyDerivedProperty{ get; set; }
}
static void Main(string[] args)
{
BaseClass myBaseObject = new BaseClass();
DerivedClass myDerivedObject = myBaseObject as DerivedClass;
myDerivedObject.MyDerivedProperty = true;
}
Ответы
Ответ 1
Нет, нет встроенного способа конвертировать класс, как вы говорите. Самый простой способ сделать это - сделать то, что вы предложили: создать конструктор DerivedClass(BaseClass)
. Другие варианты в основном выходят для автоматизации копирования свойств из базы в производный экземпляр, например. используя отражение.
Код, который вы опубликовали с помощью as
, будет скомпилирован, как я уверен, вы видели, но при запуске будет выбрано исключение с нулевой ссылкой, потому что myBaseObject as DerivedClass
будет оцениваться до null
, так как это не экземпляр DerivedClass
.
Ответ 2
Это невозможно. но вы можете использовать Object Mapper, например AutoMapper
Пример:
class A
{
public int IntProp { get; set; }
}
class B
{
public int IntProp { get; set; }
public string StrProp { get; set; }
}
В global.asax или запуске приложения:
AutoMapper.Mapper.CreateMap<A, B>();
Использование:
var b = AutoMapper.Mapper.Map<B>(a);
Он легко настраивается с помощью свободного API.
Ответ 3
Я нашел одно решение для этого, не сказав это лучшим, но он чувствует себя чистым для меня и не требует каких-либо серьезных изменений в моем коде. Мой код был похож на ваш, пока я не понял, что он не работает.
Мой базовый класс
public class MyBaseClass
{
public string BaseProperty1 { get; set; }
public string BaseProperty2 { get; set; }
public string BaseProperty3 { get; set; }
public string BaseProperty4 { get; set; }
public string BaseProperty5 { get; set; }
}
Мой производный класс
public class MyDerivedClass : MyBaseClass
{
public string DerivedProperty1 { get; set; }
public string DerivedProperty2 { get; set; }
public string DerivedProperty3 { get; set; }
}
Предыдущий метод получения заполненного базового класса
public MyBaseClass GetPopulatedBaseClass()
{
var myBaseClass = new MyBaseClass();
myBaseClass.BaseProperty1 = "Something"
myBaseClass.BaseProperty2 = "Something else"
myBaseClass.BaseProperty3 = "Something more"
//etc...
return myBaseClass;
}
До того, как я попытался это сделать, что дало мне возможность не выполнить ошибку
public MyDerivedClass GetPopulatedDerivedClass()
{
var newDerivedClass = (MyDerivedClass)GetPopulatedBaseClass();
newDerivedClass.UniqueProperty1 = "Some One";
newDerivedClass.UniqueProperty2 = "Some Thing";
newDerivedClass.UniqueProperty3 = "Some Thing Else";
return newDerivedClass;
}
Я изменил свой код следующим образом и, похоже, работает и имеет больше смысла:
Старый
public MyBaseClass GetPopulatedBaseClass()
{
var myBaseClass = new MyBaseClass();
myBaseClass.BaseProperty1 = "Something"
myBaseClass.BaseProperty2 = "Something else"
myBaseClass.BaseProperty3 = "Something more"
//etc...
return myBaseClass;
}
New
public void FillBaseClass(MyBaseClass myBaseClass)
{
myBaseClass.BaseProperty1 = "Something"
myBaseClass.BaseProperty2 = "Something else"
myBaseClass.BaseProperty3 = "Something more"
//etc...
}
Старый
public MyDerivedClass GetPopulatedDerivedClass()
{
var newDerivedClass = (MyDerivedClass)GetPopulatedBaseClass();
newDerivedClass.UniqueProperty1 = "Some One";
newDerivedClass.UniqueProperty2 = "Some Thing";
newDerivedClass.UniqueProperty3 = "Some Thing Else";
return newDerivedClass;
}
New
public MyDerivedClass GetPopulatedDerivedClass()
{
var newDerivedClass = new MyDerivedClass();
FillBaseClass(newDerivedClass);
newDerivedClass.UniqueProperty1 = "Some One";
newDerivedClass.UniqueProperty2 = "Some Thing";
newDerivedClass.UniqueProperty3 = "Some Thing Else";
return newDerivedClass;
}
Ответ 4
Вы можете реализовать преобразование самостоятельно, но я бы не рекомендовал этого. Взгляните на Decorator Pattern, если вы хотите сделать это, чтобы расширить функциональность существующего объекта.
Ответ 5
Нет, это невозможно. Единственный возможный способ -
static void Main(string[] args)
{
BaseClass myBaseObject = new DerivedClass();
DerivedClass myDerivedObject = myBaseObject as DerivedClass;
myDerivedObject.MyDerivedProperty = true;
}
Ответ 6
Нет, для этого нет встроенного преобразования.
Вам нужно будет создать конструктор, как вы упомянули, или какой-либо другой метод преобразования.
Кроме того, поскольку BaseClass не является DerivedClass, myDerivedObject будет иметь значение null, а последняя строка выше выдает исключение null ref.