我有一个方法需要允许各种输入类型。有两类参数:边界类型参数和实际数据输入参数。
边界参数例如是顺序,频率,点数和数据点数。无论实际的数据输入参数类型如何,这些边界参数都是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
}
}
答案 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");
}
完成!