C# - 如何将对象复制/创建为后代

时间:2010-03-05 22:07:37

标签: c# .net-3.5 inheritance

通过示例更容易解释。鉴于这两个类:

public class MyClassA
{
    public String Property_A { get; set; }
    public String Property_B { get; set; }
    public String Property_C { get; set; }
    public String Property_D { get; set; }
    ...
    public String Property_Y { get; set; }
}

public class MyClassB: MyClassA
{
    public String Property_Z { get; set; }
}

假设我已经完全创建了MyClassA的实例(填充了A - Y中的所有属性)。然后我需要创建一个MyClassB的实例,它与我的MyClassA实例完全相同,但填入了Property_Z(当然是自定义值)。我怎么能这样做?

执行此操作无效(抛出和无效的强制转换异常):

MyClassB myInstanceB = (myClassB) myInstanceA;
myInstance.Property_Z = myCustomValue;

自从我的C ++时代起,我就不需要做任何这样的事了。我很难过。

有什么想法吗?


更新:我找到了解决我如何创建实例的问题。它在下面。我没有把它标记为答案,因为它不完全适合我的问题。

7 个答案:

答案 0 :(得分:5)

您创建的实例是MyClassA。那是它的运行时类型,而不是MyClassB。您无法在运行时将MyClassA实例强制转换为MyClassB,因为MyClassB是一种比MyClassA更具体的类型。

您需要创建MyClassB的全新实例。清理它的一种方法是创建一个带MyClassA的构造函数,例如

public class MyClassB : MyClassA
{
    public MyClassB(MyClassA a, string z)
    {
        this.PropertyA = a.PropertyA;
        this.PropertyB = a.PropertyB;
        // etc.
        this.PropertyZ = z;
    }

    public string PropertyZ { get; set; }
}

答案 1 :(得分:2)

您可以使用Reflection来复制基类属性,如图所示here

 public void Update(MyObject o)
    {
        MyObject copyObject = ...
        Type type = o.GetType();
        while (type != null)
        {
            UpdateForType(type, o, copyObject);
            type = type.BaseType;
        }
    }


    private static void UpdateForType(Type type, MyObject source, MyObject destination)
    {
        FieldInfo[] myObjectFields = type.GetFields(
            BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);

        foreach (FieldInfo fi in myObjectFields)
        {
            fi.SetValue(destination, fi.GetValue(source));
        }
    }

答案 2 :(得分:2)

直截了当的答案:

public class MyClassA 
{ 
    public String Property_A { get; set; } 
    public String Property_B { get; set; } 
    public String Property_C { get; set; } 
    public String Property_D { get; set; } 
    ... 
    public String Property_Y { get; set; } 
} 

public class MyClassB: MyClassA 
{ 
    public MyClassB(MyClassA copy)
    {
        Property_A = copy.PropertyA;
        Property_B = copy.PropertyB;
        ...
    }
    public String Property_Z { get; set; } 
} 

像这样使用:

MyClassB o = new MyClassB(instanceOfMyClassA);
o.Property_Z = whatever;

答案 3 :(得分:2)

听起来你正在寻找一个免费的拷贝构造函数。 C#不提供一个(http://msdn.microsoft.com/en-us/library/ms173116%28VS.80%29.aspx),但您可以使用Object.MemberwiseClone或BinaryFormatter序列化程序(http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx)轻松完成。注意要知道是否需要浅拷贝或深拷贝。

答案 4 :(得分:1)

您可以定义从MyClassA到MyClassB的显式或隐式强制转换,并使用您提供的语法。

public class MyClassB : MyClassA
{
    public String Property_Z { get; set; }

    public static explicit operator MyClassB(MyClassA a)
    {
        MyClassB b = new MyClassB();
        b.Property_A = a.Property_A;
        /* ... */
        b.Property_Y = a.Property_Y;
        return b;
    }
}

答案 5 :(得分:0)

怎么样:

  1. 创建一个实现IClonable的基类,并具有所有字符串属性A到D和Z。
  2. 为MyClassA创建此类的实例。
  3. 通过克隆MyClassA创建MyClassB的实例。
  4. 在MyClassB中设置属性Z。

答案 6 :(得分:0)

这是我最终做的事情:

我创建了我的方法,用于创建和设置使用类型参数的所有属性(A-Y)。它看起来像这样:

public T MakeAMyClass<T>(AnotherClass 
where T: MyClassA : new()
{
   T returnValue = new T();
   T.Property_A = somethingToSetFrom.MakeAPropertyA();
   // Fill in the rest of the properties
}

因为类型参数可以是来自约束的类型,所以我能够传入MyClassB对象并使它们与myClassA相同。

然后我可以根据需要制作任何一个。

MyClassA myInstanceA = MakeAMyClass<MyClassA>(somethingToSetFrom);
MyClassB myInstanceB = MakeAMyClass<MyClassB>(somethingToSetFrom);
myInstanceB.Property_Z = someotherValue;

让我避免使用方法将所有属性从MyClassA复制到MyClassB。