如何获取一个类对象以在 c# 中存储另一个类对象
本文关键字:对象 另一个 存储 一个 何获取 获取 | 更新日期: 2023-09-27 18:35:43
>假设我们下面有 C# 代码,它将类 A 的实例存储在类 B 中。我想创建一个存储自己的 A 的类 B 版本。因此,当我们在 B 外部更改 A 时,B 中的内部 A 对象不会改变。
class Engine
{
public int Horesepower = 500;
}
class Vehicle
{
public Vehicle( Engine engine ) { Engine = engine; }
public Engine Engine;
}
class Program
{
static void Main( string[ ] args )
{
Engine v8 = new Engine( );
Vehicle monsterTruck = new Vehicle( v8 );
v8.Horesepower = 1000; // this changes the field Engine in yugo as well
Console.WriteLine( monsterTruck.Engine.Horesepower ); // prints 1000 instead of 500
}
}
我可以通过使用模板化的桥接类来避免C++中的此问题,该桥类在将 A 传递到 B 时克隆 A。但显然,由于某种原因,深度克隆在 C# 中似乎并没有被广泛使用(为什么?任何人都可以提供解决此存储问题的好方法。
C++代码:
template <typename T>
class Wrapper{
public:
Wrapper(const Wrapper<T> &orig){if(orig.data!=nullptr)data = orig.data->clone();}
Wrapper(const T &origdata){data = origdata.clone();}
Wrapper & operator=(const Wrapper<T> &orig){...}
...
~T(){delete data;}
private:
T *data;
}
class A{
public:
A():data(9){}
int data;
A *clone(){return new A(*this);}
}
class B{
public:
B(const Wrapper<A>& a_):ainner(a_){}
Wrapper<A> ainner;
}
int main(){
A a;
B b(a);
a.data =20;
std::cout << b.ainner.data; // prints 9 still
return 0;
}
只有当你克隆的对象包含值类型时,使用 Clone()
才能满足您的需求,但通常(如您的示例所示)您将拥有一个具有其他引用类型属性的类,并且浅拷贝(通过 Clone() )将简单地复制引用。
你想要的是深层复制,这可以通过在 ref 类型的所有属性上实现复制构造函数或通过序列化来完成。
序列化是执行深层复制的最简单方法:深度克隆对象
执行深层复制的复制构造函数示例:
class Engine
{
public Engine( ) { }
public Engine( Engine e ) { Horesepower = e.Horesepower; }
public int Horesepower = 500;
}
class Vehicle : ICloneable
{
public Vehicle( Engine engine ) { Engine = engine; }
public Vehicle( Vehicle v ) { Engine = new Engine( v.Engine ); }
public Engine Engine;
public object Clone( )
{
Vehicle newVehicle = new Vehicle( this );
return newVehicle;
}
}
请记住,您正在传递引用。 如果你将 A 的实例化副本传递给某物,你就是在将 A 的副本传递到其中(就好像你在 C 中传递了 &a)。
由于类都是引用类型,因此在 C# 中,必须在某处显式执行复制。下面是使用匿名构造函数复制您关心的值的解决方案。
static void Main( string[ ] args )
{
Engine v8 = new Engine( );
v8.Horesepower = 1000; // this changes the field Engine in yugo as well
Vehicle monsterTruck = new Vehicle( new Engine { Horesepower = v8.Horesepower } );
Console.WriteLine( v8.Horesepower ); // prints 1000
Console.WriteLine( monsterTruck.Engine.Horesepower ); // prints 1000
v8.Horesepower = 800;
monsterTruck.Engine.Horesepower = 1200;
Console.WriteLine( v8.Horesepower ); // prints 800
Console.WriteLine( monsterTruck.Engine.Horesepower ); // prints 1200
}
请记住,这是一个简单的解决方案,但如果您需要对要复制的类可能还包含的任何引用类进行深层复制,则会变得很麻烦。 在这种情况下,@TMcKeown发布的ICloneable解决方案更安全,并且总是更强大(假设您维护它!
另一种解决问题
的方法,通过使用这样的复制构造函数
using System;
public class Program
{
public static void Main()
{
A foo = new A();
B bar = new B(foo);
foo.data = 20;
Console.WriteLine(bar.a.data); // prints 9
}
}
class A
{
public int data = 9;
public A()
{
}
public A(A a)
{
this.data=a.data;
}
}
class B
{
public B(A a_) { a = new A(a_); }
public A a;
}
希望对您有所帮助