如何创建对 class 字段的引用?

How to create a reference to a class field?

我的问题是我想创建对 class 字段的引用。 (这样我可以稍后修改引用并在实际的 class 字段中显示结果。)

public static Transform operator +(Transform transform, ManipulationInformation manipulationInformation)
{
    // I would like to make this into a reference type.
    Vector3 type;
    switch (manipulationInformation.ManipulationType)
    {
        case "Scale":
            type = transform.lossyScale;
            break;
        case "Rotate":
            type = transform.rotation.eulerAngles;
            break;
        case "Move":
            type = transform.position;
            break;
    }
    switch (manipulationInformation.Direction)
    {
        case 'x':
            type = new Vector3(
                transform.position.x + manipulationInformation.NumericalSign * ModificationIncrement, 
                transform.position.y, 
                transform.position.z);
            break;
        case 'y':
            type = new Vector3(
                transform.position.x,
                transform.position.y + manipulationInformation.NumericalSign * ModificationIncrement,
                transform.position.z);
            break;
        case 'z':
            type = new Vector3(
                transform.position.x,
                transform.position.y,
                transform.position.z + manipulationInformation.NumericalSign * ModificationIncrement);
            break;
    }
    return transform;
}

与上面的代码一样,'ManipulationInformation' 包含三个 Vector3 字段,对应于 Unity 的变换 class(缩放、位置和旋转)。我希望能够添加和减去这些(因此这里的函数是重载 operator+)。我想将 'type' 变成可以保存对变换的 Vector3 之一的引用的东西,这样我就可以简化我的代码。 (一个肯定但丑陋的选择是在 'switch(manipulationInformation.ManipulationType)' 语句的每个 case 中放置一个 'switch(manipulationInformation.Direction)' 语句;然而,代码量随着 case 语句的增加呈指数级增长,而且可读性不佳。

我想知道是否有解决这种疯狂的办法。提前感谢大家!

编辑:我的意思是 'type' 是对变换的缩放、旋转和位置字段之一的引用。并使对类型的修改也将修改转换的字段。但是,我现在明白这不是必需的,我的问题是由于其他原因造成的。谢谢 Kevin Gosse。

您的方法有两个不同的部分:实际计算和赋值。您可以通过提取方法使您的代码更容易 read/maintain:

public static Transform operator +(Transform transform, ManipulationInformation manipulationInformation)
{
    var type = ApplyManipulation(manipulationInformation, transform.position);

    switch (manipulationInformation.ManipulationType)
    {
        case "Scale":
            transform.lossyScale = type;
            break;
        case "Rotate":
            transform.eulerAngles = type;
            break;
        case "Move":
            transform.position = type;
            break;
    }

    return transform;
}

private static Vector3 ApplyManipulation(ManipulationInformation manipulationInformation, Vector3 position)
{
    var offset = manipulationInformation.NumericalSign * ModificationIncrement;

    switch (manipulationInformation.Direction)
    {
        case 'x':
            return new Vector3(
                position.x + offset,
                position.y,
                position.z);
        case 'y':
            return new Vector3(
                position.x,
                position.y + offset,
                position.z);
        case 'z':
            return new Vector3(
                position.x,
                position.y,
                position.z + offset);
    }

    throw new InvalidOperationException("Unknown direction: " + manipulationInformation.Direction);
}

其实ApplyManipulation方法应该直接在ManipulationInformationclass中声明。这是一种称为 feature envy 的代码味道。从那里开始,两种类型都可以单独发展,您的代码将变成:

public static Transform operator +(Transform transform, ManipulationInformation manipulationInformation)
{
    var type = manipulationInformation.Apply(transform.position, ModificationIncrement);

    switch (manipulationInformation.ManipulationType)
    {
        case "Scale":
            transform.lossyScale = type;
            break;
        case "Rotate":
            transform.eulerAngles = type;
            break;
        case "Move":
            transform.position = type;
            break;
    }

    return transform;
}

您可以通过引入第三种类型来进一步减少耦合,这种类型知道如何在 Transform 上应用 ManipulationInformation(整个 switch (manipulationInformation.ManipulationType) 代码),但这可能有点矫枉过正那一点。

我认为您 + 超载了太多。如果你不关心这个,那就继续往下看。

你可能应该这样做:

Action<Transform, Vector3> action;
switch (manipulationInformation.ManipulationType)
{
    case "Scale":
        action = (t, v) => t.lossyScale = v;
        break;
    case "Rotate":
        action = (t, v) => t.rotation.eulerAngles = v;
        break;
    case "Move":
        action = (t, v) => t.position = v;
        break;
}

switch (manipulationInformation.Direction)
{
    case 'x':
        action(transform, new Vector3(
            transform.position.x + manipulationInformation.NumericalSign * ModificationIncrement, 
            transform.position.y, 
            transform.position.z));
        break;
    case 'y':
        action(transform, new Vector3(
            transform.position.x,
            transform.position.y + manipulationInformation.NumericalSign * ModificationIncrement,
            transform.position.z));
        break;
    case 'z':
        action(transform, new Vector3(
            transform.position.x,
            transform.position.y,
            transform.position.z + manipulationInformation.NumericalSign * ModificationIncrement));
        break;
}

因为 transform 不是值类型,它可以被传递,所以你可以用一些委托魔法来做到这一点。