Преобразовать базовый класс в производный класс

Возможно ли в C# явно преобразовать объект базового класса в один из его производных классов? В настоящее время я думаю, что мне нужно создать конструктор для моих производных классов, который принимает объект базового класса в качестве параметра и копирует значения свойств. Мне не очень нравится эта идея, поэтому я хотел бы избежать ее, если это возможно.

Это не похоже на работу (объект создается как новая база, поэтому память не должна выделяться для дополнительных членов производного класса), но C#, кажется, позволяет мне это сделать:

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;
}

6 ответов

Решение

Нет, нет встроенного способа конвертировать класс, как вы говорите. Самый простой способ сделать это - сделать то, что вы предложили: создать DerivedClass(BaseClass) конструктор. Другие варианты в основном выходили бы для автоматизации копирования свойств из базы в производный экземпляр, например, используя отражение.

Код, который вы разместили с помощью as будет компилироваться, как я уверен, вы видели, но при запуске выдает исключение нулевой ссылки, потому что myBaseObject as DerivedClass будет оценивать null, так как это не пример DerivedClass,

Это невозможно. но вы можете использовать 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.

Я нашел одно решение, не говоря о том, что оно лучшее, но мне кажется, что оно чистое и не требует каких-либо серьезных изменений в моем коде. Мой код был похож на ваш, пока я не понял, что он не работает.

Мой базовый класс

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;
}

новый

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;
}

новый

public MyDerivedClass GetPopulatedDerivedClass()
{
   var newDerivedClass = new MyDerivedClass();

   FillBaseClass(newDerivedClass);

   newDerivedClass.UniqueProperty1 = "Some One";
   newDerivedClass.UniqueProperty2 = "Some Thing";
   newDerivedClass.UniqueProperty3 = "Some Thing Else";

   return newDerivedClass;
}

Вы можете осуществить преобразование самостоятельно, но я бы не советовал. Взгляните на Pat tern Decorator Pattern, если вы хотите сделать это, чтобы расширить функциональность существующего объекта.

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

Кроме того, поскольку BaseClass не является DerivedClass, myDerivedObject будет иметь значение null, а последняя строка выше выдаст исключение null ref.

Нет, это невозможно. Единственный возможный способ

static void Main(string[] args)
{
    BaseClass myBaseObject = new DerivedClass();
    DerivedClass myDerivedObject = myBaseObject as DerivedClass;

    myDerivedObject.MyDerivedProperty = true;
}
Другие вопросы по тегам