有必要编写一个泛型方法,该方法接受一个数字数组(int、long 等),向每个元素添加一些相同类型的常量,然后返回一个新数组。我试图这样实现它:
static public T[] SomeMethod<T>(T[] myArray, T myConst)
{
T[myArray.Length] resultArray = default(T);
for (int counter = 0; counter < myArray.Length; counter++)
{
resultArray[counter] = myArray[counter] + myConst;
}
return resultArray;
}
首先,根据 Shield 4.0,这种泛型方法的语法如下:return_type method_name<list_of_type_parameters>(list_of_parameters) {...}。这里马上就出现了一个问题——是否有必要在方法名称后的尖括号中指定参数列表?之前实现其他方法,我没有这样做,一切正常。这是否意味着没有必要?其次,在此方法中声明新 resultArray 的局部变量时,出现错误,解释如下:“'T' is an type that is not valid in this context.” 但为什么?毕竟,代替所有 <> 将有一个类型作为参数传递,包括我在哪里创建一个新的结果数组。为什么会出现这个错误?我也尝试至少部分解决这个问题,
static public T[] SomeMethod<T>(T[] myArray, T myConst)
{
for (int counter = 0; counter < myArray.Length; counter++)
{
myArray[counter] = myArray[counter] + myConst;
}
return myArray;
}
但是,在这种情况下,在行 myArray[counter] = myArray[counter] + myConst; 发生错误“运算符'+'不能应用于'T'和'T'类型的操作数”。我也不明白这个错误。我在做什么错,以及如何解决问题?
如果您仍然需要将逻辑移出循环,我可以提供几个选项:
通过 lambda 公开逻辑:
这里编译器已经知道参数的类型,所以操作符不会有问题。使用一个元素的所有逻辑都在 lambda 函数中取出。
使用反射(纯理论):
这个选项的问题是原始类型没有 + 运算符,这个对原始数字的操作不再由尖锐本身执行。因此,纯粹从技术上讲,调用你的类将类似于 instance += anotherInstance;
最简单的方法是使用
dynamic. 但是,这很慢,并且可能在运行时崩溃。对于初学者来说,为每个操作创建一个单独的方法是没有意义的。因此,最好将转换操作作为参数传递。
让我们从一个简单的例子开始
这个例子有两个明显的缺点:
让我们解决这个问题并将其实现为扩展方法:
它已经看起来更好了。它可以这样使用:
但这种方法也有缺点。
例如,这个表达式
它将分配内存 3 次,尽管我们实际上只需要一次。可以做什么?为了扩大消费者的圈子,您不仅可以在数组上运行该方法,还可以在枚举的所有内容上运行该方法。为了尽量减少内存分配,可以根本不分配内存,而是使用惰性枚举。它看起来像什么:
这样做的好处是现在的表达式
在明确枚举结果之前,根本不会计算任何东西。大约根据这种机制,Linq Select功能可以工作,也可以在您的情况下使用。
也就是说,其实表达式可以改写成这样
它和我们刚刚写的一样,只是不使用我们的函数。
你确定你需要 SomeMethod 吗?因为您可以在需要的地方使用 Linq。