web-dev-qa-db-ja.com

基本クラスを派生クラスに変換する

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

いいえ、あなたが言うようなクラスを変換する組み込みの方法はありません。これを行う最も簡単な方法は、提案したことを行うことです:DerivedClass(BaseClass)コンストラクターを作成します。他のオプションは基本的に、ベースから派生インスタンスへのプロパティのコピーを自動化するために出てきます。反射を使用します。

asを使用して投稿したコードはコンパイルされますが、ご存知のとおり、実行するとnull参照例外がスローされます。これは、myBaseObject as DerivedClassnullのインスタンスではないため、DerivedClassに評価されるためです。

85
Tim S.

それは可能ではありません。ただし、 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で簡単に設定できます。

47
Mahmoodvcs

私はこれに対する解決策を見つけましたが、それが最良の解決策であるとは言いませんが、それは私にとってクリーンであり、コードに大きな変更を加える必要はありません。私のコードは、それが機能しないことに気付くまで、あなたのコードに似ていました。

私の基本クラス

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

自分で変換を実装できますが、それはお勧めしません。既存のオブジェクトの機能を拡張するためにこれを行いたい場合は、 装飾パターン をご覧ください。

6
Matthias Meid

いいえ、これには組み込みの変換はありません。前述のようにコンストラクター、または他の変換メソッドを作成する必要があります。

また、BaseClassはDerivedClassではないため、myDerivedObjectはnullになり、上記の最後の行はnull ref例外をスローします。

1
Erix

いいえ、不可能です。可能な唯一の方法は

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

    myDerivedObject.MyDerivedProperty = true;
}
1
Jan P.