c# = operator problem
In C#, I have a simple 3D vector class.
static void Main(string[] args)
{
Vector3D a, b;
a = new Vector3D(0, 5, 10);
b = new Vector3D(0, 0, 0);开发者_如何学Python
b = a;
a.x = 10;
Console.WriteLine("vector a=" + a.ToString());
Console.WriteLine("vector b=" + b.ToString());
Console.ReadKey();
}
the output is,
vector a= 10, 5, 10
vector b= 10, 5, 10
I assign a before i change a.x to 10. So i was expecting
vector a= 10, 5, 10
vector b= 0, 5, 10
From what i understand = operator assigns a reference to object like a pointer? And in C# i cant overload = operator.
Do i have to manually assign each property?
Yes, because Vecor3D is a class this is quite correct.
Classes are reference types and your b = a;
statement does not copy a Vector3D instance but a reference to an instance.
If you want to 'clone' the instances, you could add the IClonable interface, but that is more or less abandoned.
A better solution for an <X,Y,Z>
type might be to make it a struct. Structs are values types and the meaning of b = a;
would change (towards what you want).
A 3D point meets all the criteria for a struct (small, no identity). The preferred way is to design it as immutable.
Yes, "= operator assigns a reference to object like a pointer", as you put it. Thus, both a
and b
reference the same single object in memory. (The object previously referenced by b
is not referenced any more and will be garbage collected.)
There are multiple ways to overcome this problem:
Make
Vector3D
a struct instead of a class. Structs are value types instead of reference types, sob = a
copies the contents ofa
to variableb
.Implement a
Clone
method in yourVector3D
class (previously, this would mean implementingICloneable
, but this is no longer recommended). Alternatively, you could create aVector3D
constructor that takes another vector as a parameter and creates a copy.Manually copy the three values yourself (
b = new Vector3D(a.x, a.y, a.z)
), if you cannot change the implementation ofVector3D
.
You may want to change your Vector3D
class to a struct. That would let you work with a value type instead of a reference type.
Your other option is to implement ICloneable
or use some other method to create a deep copy of your object.
Yes, reference types are assinged by reference.
If you want to have a separate instance, you want to CLONE your instance.
Create a Vector3D.Clone() method, which would look something like this:
public Vector3D Clone()
{
return new Vector3D(this.x, this.y, this.x);
}
Then your Main should look like this:
static void Main(string[] args)
{
Vector3D a, b;
a = new Vector3D(0, 5, 10);
b = new Vector3D(0, 0, 0);
b = a.Clone();
a.x = 10;
Console.WriteLine("vector a=" + a.ToString());
Console.WriteLine("vector b=" + b.ToString());
Console.ReadKey();
}
But as others have said, something as small as a Vector3D would be better suited as an immutable struct
You can make it a struct like Henk says. And you can add a constructor
struct Vector3D
{
public int x;
public int y;
public int z;
public Vector3D(int x, int y, int z)
{
this.x = x;
this.y = y;
this.z = z;
}
public override string ToString()
{
return string.Format("{0}, {1}, {2}", x, y, z);
}
}
You could also do this without adding the constructor.
b = new Vector3D() {x=0, y=0, z=0};
No need to use a struct
, I suggest you should design your Vector3D
as an immutable class. Here are some good examples. Of course, a.x = 10
won't be possible for an immutable class.
精彩评论