结构扩展方法

mcp*_*man 1 c# unity-game-engine

使用代码:

someVector.FixRounding(); //round vector's values to integers if the difference is 1 epsilon
float x = someVector.x; //still getting old value
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)

虽然Mathf.Approximately返回true,但FixRounding方法实际上并不会更改向量的值.

Jon*_*eet 6

本声明:

public static void FixRounding(this Vector3 v)
Run Code Online (Sandbox Code Playgroud)

...表示v正在通过值传递,并且它是一个结构,假设文档是正确的.因此,您对其所做的任何更改都将对调用者不可见.你需要使它成为常规方法,并通过v引用传递:

public static void FixRounding(ref Vector3 v)
Run Code Online (Sandbox Code Playgroud)

并称之为:

TypeDeclaringMethod.FixRounding(ref pos);
Run Code Online (Sandbox Code Playgroud)

这是一个扩展方法的演示,试图修改值失败传递的结构:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

现在如果Vector3是一个类,打印的第二行将是x = 20; Y = 40; z = 60 ...但是因为它是一个结构,修改传递的值不会从调用者的角度改变它.通过引用传递它,因此第三行输出.