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

时间:2017-05-23 06:22:04

标签: c# .net unity3d pass-by-reference

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

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'包含三个与Unity的变换类(比例,位置和旋转)对应的Vector3字段。我希望能够添加和减去这些(因此这里的函数是重载operator +)。我想将'type'变成可以引用transform的Vector3之一的东西,以便我可以简化我的代码。 (一个肯定的但丑陋的选择是在'switch(manipulationInformation.ManipulationType)'语句的每个情况下放置一个'switch(manipulationInformation.Direction)'语句;但是,代码量随着更多case语句呈指数增长而不是很可读的。

我想知道是否有解决这种疯狂的方法。提前全部感谢!

编辑:我的意思是'type'是对transform的scale,rotation和position字段之一的引用。并使其对类型的修改也会修改transform的字段。但是,我现在明白这不是必要的,我的问题是由于其他原因。谢谢Kevin Gosse。

2 个答案:

答案 0 :(得分:2)

我认为你过多地超载了+。如果您不关心这一点,请继续阅读。

你应该做这样的事情:

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不是值类型,因此可以传递它,因此您可以使用一些委托魔法来执行此操作。

答案 1 :(得分:1)

您的方法有两个不同的部分:实际计算和分配。您可以通过提取方法使代码更容易阅读/维护:

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方法应该直接在ManipulationInformation类中声明。这是一种称为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;
}

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