C#方法重载

时间:2012-02-23 20:14:45

标签: c# overloading

我有一个方法需要允许各种输入类型。有两类参数:边界类型参数和实际数据输入参数。

边界参数例如是顺序,频率,点数和数据点数。无论实际的数据输入参数类型如何,这些边界参数都是int类型并且是通用的。

实际的输入参数可以是以下类型:byte,int,short,uint,float,double,decimal,long等。为了进一步复杂化,实际输入数据可以是单个数据,也可以是列表或数组那种类型。因此,实际输入可能是List或uint []等。此输入最终转换为double类型 - 单个数据或双重[]。

该方法由三部分组成:第一部分检查边界参数的有效性。此部分始终适用于实际输入数据类型的方面。第二部分检查并处理输入数据参数。该部分根据输入数据的类型而改变。第三部分对数据进行计算,再次很常见。

我考虑过泛型,我考虑过使用泛型的标准重载,但两者看起来都效率低下。我已经提出了我认为可行的解决方案,但我会赞赏评论:我的方法计算效率高,是否有更好的方法来做到这一点。您的意见将不胜感激。

这就是我目前所拥有的:

// ... create lists to store data
static List<double> aList = new List<double>(8);
static List<double> fList = new List<double>(8);

public static double[] MyMethod(int numPts, int numData, object aValue, object fValue)
{
    // ... part 1
    if (numData < 2) throw new ArgumentOutOfRangeException("numberData must be >= 2.");
    if (numPts < 2) throw new ArgumentOutOfRangeException("numberPoints must be >= 2.");
    if (numData < numPts) throw new ArgumentOutOfRangeException("numberData must be
        >= numPts.");

    // ... part 2
    if (aValue is byte || aValue is short || aValue is int || aValue is long ||
        aValue is float || aValue is double || aValue is decimal ||
        aValue is List<byte> || aValue is byte[] || aValue is List<short> ||
        aValue is short[] || aValue is List<int> || aValue is int[] ||
        aValue is List<float> || aValue is float[] || aValue is List<double> ||
        aValue is double[])
    { }
    else throw new ArgumentException("a values must be of a numeric type.");

    double a = 0.0;
    if (aValue is byte || aValue is short || aValue is int || aValue is long ||
        aValue is float || aValue is double || aValue is decimal)
    {
        a = (double)aValue;
        // ... store individual values
        aList.Add(a);

        // ... create the x variable vector
        double[] x = aList.ToArray();     // a values
    }
    else if (aValue is List<byte> || aValue is List<short> || aValue is List<int> ||
             aValue is List<float> || aValue is List<double>)
    {
        // ... get the runtime type of the aValue object
        Type t = aValue.GetType();
        // ... convert the aValue object to a generic list
        IList tmp = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(t));
        // ... convert the generic list to a strongly typed list
        List<double> aValuesList = tmp.Cast<double>().ToList();

        // ... create the x variable vector
        double[] x = aValuesList.ToArray();     // a values
    }
    else
    {
        // ... process the vector input
        // ... get the runtime type of the aValue object
        Type t = aValue.GetType();
        // ... convert the aValue object to an array
        Array tmp = Array.CreateInstance(typeof([]).MakeGenericType(t), aValue.Length);
        // ... convert the generic array to a strongly typed array
        double[] x = tmp.Cast<double>().ToArray();
    }

    // ... part 3
    {
        // ... do calculations
    }
}

5 个答案:

答案 0 :(得分:0)

真的不想这样做。

由于您的输入非常复杂,并且有很多检查,因此您应该将所有输入放入一个将负责所有检查的类中。各种类型的输入只是成为派生类。

答案 1 :(得分:0)

让它接受double[]。让调用代码按下他们的数据到正确的格式,或者为其他数据类型提供重载。

例如,如果您的方法是:

public double[] Calculate(double[] aValue, double[] fValue, ...)
{
}

您可以提供类似的重载:

public double[] Calculate(double aValue, double fValue, ...)
{
    return Calculate(new double[]{aValue}, new double[]{fValue}, ...);
}

public double[] Calculate(IEnumerable<double> aValue, IEnumerable<double> fValue, ...)
{
    return Calculate(aValue.ToArray(), fValue.ToArray(), ...);
}

要涵盖其他数据类型,可以使用以下内容减少重载次数:

public double[] Calculate<T>(T aValue, T fValue) where T : IConvertible
{
    return Calculate(aValue.ToDouble(), fValue.ToDouble(), ...);
}

public double[] Calculate<T>(IEnumerable<T> aValue, IEnumerable<T> fValue) where T : IConvertible
{
    return Calculate(aValue.Select(x=>x.ToDouble()), fValue.Select(x=>x.ToDouble()), ...);
}

这应该涵盖所有其他原始数据类型,这就是你的所有例子。

如果这样做,计算方法中的代码将减少到:

public double[] Calculate(double[] aValue, double[] fValue, int numData, int numPts)
{
    if (numData < 2) throw new ArgumentOutOfRangeException("numberData must be >= 2.");
    if (numPts < 2) throw new ArgumentOutOfRangeException("numberPoints must be >= 2.");
    if (numData < numPts) throw new ArgumentOutOfRangeException("numberData must be
    >= numPts.");

    // do calculation
}

......这简单得多。

答案 2 :(得分:0)

我认为一堆重载将是可​​行的方法。每一个都很简单,只需调用main方法即可。但是,所有数据类型测试都是由编译器完成的,而不是由你的巨大if语句完成的。您还可以在每个重载中设置一个标志,告诉您的主要方法,如果您收到一个号码,列表&lt;&gt;或者数组(或者你需要处理的其他任何东西)。例如:

enum DataType { SingleNumber, NumberList, NumberArray }

// one of many overloads
public static double[] MyMethod(int numPts, int numData, byte aValue, object fValue) {
  return MyMethod(numPts, numData, (object)aValue, fValue, DataType.SingleNumber);
}

答案 3 :(得分:0)

你有2个阶段......首先你要检查所有内容,然后分别aValue

所以,把它分开。

然后,您可以使用泛型来调用aValue类型的特定函数

void foo<T> (T aValue) where T : struct { } //value type

void foo<T> (List<T> aValue) where T : struct { } //List of value type

void foo<T> (T[] aValue) where T : struct { } //Array of value type

如果您想要更好的数字类型约束:Generic constraint to match numeric types

答案 4 :(得分:0)

如果您不想要求调用者将其数据转换为double[],那么无论如何都要在被调用者中执行此操作。但请将其委托给另一个功能!阅读正在发生的事情要容易得多:

public static double[] MyMethod(int numPts, int numData, object aValue, object fValue)
{
    //validation omitted for brevity
    // ... part 2
    double[] aValues = ToDoubleArray(aValue);
    // ... the rest
}

完成!

这是一个实现,尽管无疑是一个更强大和/或更有效的实现:

private double[] ToDoubleArray(object aValue)
{
    if (aValue is byte || aValue is short || aValue is int || aValue is long
        || aValue is float || aValue is double || aValue is decimal)
        return new double[] { Convert.ToDouble(aValue) };

    if (aValue is IEnumerable)
        return ((IEnumerable)aValue).Select(Convert.ToDouble).ToArray();

    throw new ArgumentException("The value was of an unsupported type", "aValue");
}

完成!