【问题标题】:How to create a reference to a class field?如何创建对类字段的引用?
【发布时间】:2017-10-22 22:58:33
【问题描述】:

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

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 的变换类(缩放、位置和旋转)。我希望能够添加和减去这些(因此这里的函数是重载 operator+)。我想将“类型”制作成可以引用转换的 Vector3s 之一的东西,这样我就可以简化我的代码。 (一个可靠但丑陋的选择是在“switch(manipulationInformation.ManipulationType)”语句的每个 case 中放置一个“switch(manipulationInformation.Direction)”语句;但是,代码量随着 case 语句的增加呈指数增长,而不是非常可读。

我想知道是否有解决这种疯狂的方法。在此先感谢大家!

编辑:我的意思是“类型”是对变换的比例、旋转和位置字段之一的引用。并使其修改类型也将修改变换的字段。但是,我现在明白这不是必需的,我的问题是由于其他原因。谢谢凯文·戈斯。

【问题讨论】:

  • 所以manipulationInformation.ManipulationType 中的每个选项都有三个(或更多)选项manipulationInformation.Direction?比您必须做同样的事情,但是您应该考虑将您重复的所有内容插入到一个方法中以减少代码加倍。还是我弄错了,例如,您有什么选择?你的manipulationInformation.ManipulationType 等于"Scale"(顺便说一句。你最好不要使用枚举而不是字符串)?你可以缩放到 x 方向,你可以旋转离子 x 轴并移动到 x 方向,不是吗?
  • 为什么将type 设置为依赖于ManipulationType 的值只会被另一个switch 语句覆盖?
  • 您似乎也过多地重载了 + 运算符。惯例是使用+进行平移,在Vector3和标量之间由*执行均匀缩放,在Vector3和矩阵之间由*执行旋转。
  • 不明白代码背后的目的。至于修改参考,您始终可以访问转换的 Vector3 属性并为其分配不同的值。那么问题是什么?你只是在寻找代码是否可以缩短吗?

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


【解决方案1】:

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

你可能应该这样做:

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 不是值类型,它可以被传递,所以你可以用一些委托魔法来做到这一点。

【讨论】:

  • 这太美了!我从来没有想过使用代表来解决这个问题的可能性。谢谢。
【解决方案2】:

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

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;
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-19
    • 1970-01-01
    • 1970-01-01
    • 2022-11-02
    • 1970-01-01
    相关资源
    最近更新 更多