- Home /
Extension Method
Hi guys, I've created an extension method for a Vector2 as follows:
public static void RemoveSmallestComponent ( this Vector2 vector)
{
if ( Mathf.Abs ( vector.x ) > Mathf.Abs ( vector.y ) )
{
vector.y = 0;
}else{
vector.x=0;
}
}
...and calling it as follows:
Vector2 test = new Vector2 ( 0.1, 0.9 );
test.RemoveSmallestComponent();
Within the actual code it's behaving as it should (stripping out the smallest component of the vector) but it's not actually changing the vector that is calling it.
Where am I going wrong? Thanks for any advice!
Answer by vexe · Dec 15, 2013 at 02:56 PM
That's because Vector2
is a value-type - (a struct). And when you deal with value-types, you deal with copies of them, not references. So when you pass a Vector2
to a method and change that vector's value inside, you won't affect the actual Vector2
that you passed because a copy of the vector gets created and passed (i.e. not the same storage location) (which is a reason why they recommend for structs not to be big in size. If they're big, it's gonna be an overhead each time you pass your struct to a method, cause a copy of it has to be created in order to get passed...)
Vector2 v1 = new Vector2(1, 2);
Reset(v1);
print(v1); // still prints 1, 2
void Reset(Vector2 v)
{
v.x = v.y = 0;
}
This is what is happening with your extension - is that a copy of your Vector2 is getting passed. Normally, you'd solve this by passing the parameter by reference, like so:
void Reset(ref Vector2 v)
{
v.x = v.y = 0;
}
Reset(ref v1);
Now, you're passing the same storage location in memory of the vector, not a copy of it (v1 and v, are two names for the same thing - same storage location).
But with extension methods, you can't pass by reference (see why). A simple solution is to return the vector again, so:
public static Vector2 RemoveSmallestComponent(this Vector2 vector)
{
if (Mathf.Abs(vector.x) > Mathf.Abs(vector.y)) {
vector.y = 0;
}
else {
vector.x = 0;
}
return vector;
}
And calling it like:
Vector2 v = new (1, 2);
v = v.RemoveSmallestComponent();
Fantastic explanation - thanks so much for taking the time!
Sure no problem. I'd take a look at this eye-opener from Jon Skeet about value-types vs reference types, and passing byvalue vs byreference. Amazing resource http://www.yoda.arachsys.com/csharp/parameters.html
@vexe: Yes it's a great link, but a bit long-winded. But yes, it's a quite common belief, even under experienced programmers, that reference types are "passed by reference", which is simply not true ;)