mcpiroman
mcpiroman

Reputation: 355

Struct extension methods

With code:

someVector.FixRounding(); //round vector's values to integers if the difference is 1 epsilon
float x = someVector.x; //still getting old value

public static void FixRounding(this Vector3 v)
{
    if (Mathf.Approximately(v.x, Mathf.Round(v.x))) v.x = Mathf.Round(v.x);
    if (Mathf.Approximately(v.y, Mathf.Round(v.y))) v.y = Mathf.Round(v.y);
    if (Mathf.Approximately(v.z, Mathf.Round(v.z))) v.z = Mathf.Round(v.z);
}

the FixRounding method doesn't actually change the vector's values although Mathf.Approximately returns true.

Upvotes: 1

Views: 1308

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1500735

This declaration:

public static void FixRounding(this Vector3 v)

... means v is being passed by value, and it's a struct, assuming the documentation is correct. Therefore any changes you make to it won't be visible to the caller. You need to make it a regular method, and pass v by reference:

public static void FixRounding(ref Vector3 v)

and call it as:

TypeDeclaringMethod.FixRounding(ref pos);

Here's a demonstration of extension methods that try to modify structs passed by value failing:

using System;

struct Vector3
{
    public float x, y, z;

    public override string ToString() => $"x={x}; y={y}; z={z}";
}

static class Extensions
{
    public static void DoubleComponents(this Vector3 v)
    {
        v.x *= 2;
        v.y *= 2;
        v.z *= 2;
    }

    public static void DoubleComponentsByRef(ref Vector3 v)
    {
        v.x *= 2;
        v.y *= 2;
        v.z *= 2;
    }
}

class Test
{
    static void Main()
    {
        Vector3 vec = new Vector3 { x = 10, y = 20, z = 30 };
        Console.WriteLine(vec); // x=10; y=20; z=30
        vec.DoubleComponents();
        Console.WriteLine(vec); // Still x=10; y=20; z=30
        Extensions.DoubleComponentsByRef(ref vec);
        Console.WriteLine(vec); // x=20; y=40; z=60
    }
}

Now if Vector3 were a class, the second line printed would be x=20; y=40; z=60... but because it's a struct, modifying the value that's passed doesn't change it from the caller's perspective. Passing it by reference fixes that, hence the third line of output.

Upvotes: 6

Related Questions