【问题标题】:How to write a method that may return two different kinds of types?如何编写一个可能返回两种不同类型的方法?
【发布时间】:2014-06-22 03:38:02
【问题描述】:

我有一个名为 Vector 的类,我正在对它实现乘法运算符,这是我的实现:

public static Object operator *(Vector x, Vector y)
{

    //Possible return objects
    Matrix multiplicationResultMatrix;
    float multiplicationResultScalar = 0f;


    if (x.VectorType != y.VectorType)
    {
        if (x.Length == y.Length)
        {
            if ((x.VectorType == VectorType.Row) && (y.VectorType == VectorType.Column))
            {
                for (ulong i = 0; i < x.Length; i++)
                {
                    multiplicationResultScalar += x[i] * y[i];
                }
            }
            else
            {
                if ((x.VectorType == VectorType.Column) && (y.VectorType == VectorType.Row))
                {
                    multiplicationResultMatrix = new Matrix(x.Length);
                    for (ulong j = 0; j < x.Length; j++)
                    {
                        for (ulong i = 0; i < x.Length; i++)
                        {
                            multiplicationResultMatrix[i, j] += x[i] * y[j];
                        }
                    }
                }
            }
        }
        else
        {
            throw new ArithmeticException("Unhandled Arithmetic Exception, Multiplication of two vectors of different length is not allowed");
        }
    }
    else
    {
        throw new ArithmeticException("Unhandled Arithmetic Exception, Multiplicating vectors of the same type is not allowed");
    }

    //What should I return
    return ?
}

我应该如何定义返回类型?我曾想过将它们装箱,并在食用时拆箱,但我认为这不是一个好的安全解决方案。

更新:

我也考虑过只返回一个矩阵对象,因为标量是一个 1x1 矩阵,问题是矩阵类有一些复杂的方法和属性,这些方法和属性在 1x1 的情况下不能正常工作(这将强迫我添加一些代码),加上我想最小化和优化计算,我正在处理数百万范围内的矩阵乘法。

【问题讨论】:

  • 对于这段代码,您应该将返回类型定义为Matrix,并完全忘记标量结果分支。调用者可以检查结果(无论您选择什么,它都必须这样做),看到它是 1x1 并提取标量值。
  • 这个问题似乎离题了,因为它可能属于代码审查。
  • @Jon : 检查我的更新
  • 我在这里进行猜测,但是:1) 如果Matrix 类不能与 1x1 矩阵一起正常工作,那么只需将该类至少有一个应该修复的错误,时期。说您必须添加代码也是一种危险信号,因为通常正是“附加”代码导致了这些问题,解决方案是删除它。 2)“最小化和优化计算”太笼统而没有用处。
  • @Jon : 谢谢你的解释,我会听取你的建议

标签: c# .net methods return boxing


【解决方案1】:

您应该避免根据输入参数的值更改返回类型(与编译时已知的静态类型相反)。这使得调用者完成了你方法工作的一部分,即找出返回了什么。

有两种解决方案:

  • 始终返回相同类型的对象 - 您的方法将返回 NxN 矩阵或 1x1 矩阵,具体取决于列或行是否在前,或者
  • 定义不同类型的单独方法 - 不使用运算符,而是创建 MultiplyRowColMultiplyColRow 方法,返回不同类型的对象。

从技术上讲,第一个解决方案更好,因为逐列相乘会产生一个包含单个元素的矩阵,而不是一个标量。

【讨论】:

    【解决方案2】:

    C# 对 sum 类型的支持非常有限,但这是可能的。有一个nice implementation of a Discriminated Union here on StackOverFlow。使用它,您的方法可能如下所示:

    public static Union2<Matrix, float> operator *(Vector x, Vector y)
    {
        (...)
        return multiplicationResultMatrix != null 
            ? new Union2<Matrix, float>.Case1(multiplicationResultMatrix)
            : new Union2<Matrix, float>.Case2(multiplicationResultFloat);
    }
    

    请注意,在这种情况下,我实际上并不建议这样做,因为我同意其他发帖人的观点,即始终返回矩阵会是更好的设计。但你知道,这是可行的。

    【讨论】:

      【解决方案3】:

      如果它们没有共同的基类或接口,那么Object 是您唯一的选择。

      【讨论】:

      • + 1 我就是这样做的。只要确保在取回类型时使用自省来检查类型:)
      • 这种情况下返回object也是没用的。如果你要强制调用者检查结果,为什么还要返回不同的类型呢?我没有投反对票,只是略微投反对票。
      • 嗯,是的...但是如果您真的想返回 2 种没有公共基类或接口的不同类型的对象,那么没有其他方法可以做到。如果这不是一个选项,那么您将不得不提出一个不返回不同类型的不同模式。
      • @BradleyUffner:所以“return object”是一个技术上正确的答案。但这是一个不好的正确答案,因为它解决的唯一问题是简单的问题(“编译器不会让我!”),它让调用者处理困难的问题(“我如何使这个方法最有用?” )。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-18
      相关资源
      最近更新 更多