【问题标题】:Determine which method to call based on array size and number of arguments根据数组大小和参数数量确定要调用的方法
【发布时间】:2013-08-06 10:32:21
【问题描述】:

我有一个必须完成的繁重计算算法。为了使其尽可能高效,我根据参数的数量将其分为五种方法。这使我能够尽可能地节省开支。也就是说,我不希望我的用户知道这一点。

public AnalysisResult[] PerformAnalysis(double[] Inputs, double[] Outputs, int[][] Coefficients)
{
    AnalysisResult[] AR = new AnalysisResult[Coefficients.Length];

    for (int i = 0; i < Coefficients.Length; i++)
        AR[i] = GetResults(Inputs, Outputs, /* Based on length of Coefficients[i]*/ );

    return AR;
}

private AnalysisResult GetResults(double[] Inputs, double[] Outputs, int A)
{
    // Do stuff
}

private AnalysisResult GetResults(double[] Inputs, double[] Outputs, int A, int B)
{
    // Do stuff
}

private AnalysisResult GetResults(double[] Inputs, double[] Outputs, int A, int B, int C)
{
    // Do stuff
}

private AnalysisResult GetResults(double[] Inputs, double[] Outputs, int A, int B, int C, int D)
{
    // Do stuff
}

private AnalysisResult GetResults(double[] Inputs, double[] Outputs, int A, int B, int C, int D, int E)
{
    // Do stuff
}

如您所见,我希望只有一个公共方法可供用户调用算法。我想知道是否有一种简单的方法可以根据传递给PerformAnalysis 的数组的长度来确定调用哪个私有方法?

有什么建议吗?

到目前为止,我的方法是基于数组长度的 switch 语句,但我认为有更好的方法。

public AnalysisResult[] PerformAnalysis(double[] Inputs, double[] Outputs, int[][] Coefficients)
{
    AnalysisResult[] AR = new AnalysisResult[Coefficients.Length];

    for (int i = 0; i < Coefficients.Length; i++)
        switch (Coefficients[i].Length)
        {
            case 1:
                AR[i] = GetResults(Inputs, Outputs, Coefficients[i][0]);
                break;
            case 2:
                AR[i] = GetResults(Inputs, Outputs, Coefficients[i][0], Coefficients[i][1]);
                break;

            // Etc
        }                

    return AR;
}

【问题讨论】:

  • 我认为方法的行为会根据参数的数量而有所不同?
  • switch 很干净。如果您需要坚持使用采用数组数组的单个公共方法,则没有理由更改任何内容。

标签: c# .net arrays algorithm overloading


【解决方案1】:

嗯,你在循环中多次使用Coefficients[i] 对我来说是一种痛苦,首先。我要做的第一个重构是:

// Names changed to fit .NET conventions
public AnalysisResult[] PerformAnalysis(int[][] coefficients)
{
    return Array.ConvertAll(coefficients, GetResult);
}

private AnalysisResult GetResult(int[] input)
{
    switch (input.Length)
    {
        case 1: return GetResult(input[0]);
        case 2: return GetResult(input[0], input[1]);
        case 3: return GetResult(input[0], input[1], input[2]);
        case 4: return GetResult(input[0], input[1], input[2], input[3]);
        case 5: return GetResult(input[0], input[1], input[2], input[3], input[4]);
        default:
            throw new ArgumentException("Invalid number of inputs: " + input.Length);
    }
}

这是假设您真的想为不同的情况保留不同的方法,这是问题中的假设。

【讨论】:

  • 这在 java 中会很容易,因为 JDK5 提供了 var args,称为变量参数。所以你的方法可能就像 private AnalysisResult GetResult(int... input)
  • @AKS:C# 具有相同的能力 - 它将是 GetResult(params int[] input)。但是 OP 希望针对不同的情况有不同的方法。
【解决方案2】:

如果你愿意,可以使用反射:

for (int i = 0; i < Coefficients.Length; i++) {
    // Get all private methods named GetResults with a number of parameters equal to Cofficients[i].Length
    var methodToCall = this.GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic).Where(mi => mi.Name == "GetResults" && mi.GetParameters().Count() == Coefficients[i].Length);
    // Invoke that method via reflection
    AR[i] = methodToCall.Invoke(this, Cofficients[i]);
}

【讨论】:

    猜你喜欢
    • 2016-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-09
    • 2016-08-05
    • 2015-10-24
    • 2016-01-09
    相关资源
    最近更新 更多