C# - 返回泛型数组类型
本文关键字:数组 类型 泛型 返回 | 更新日期: 2023-09-27 17:56:51
如果我有一个简单的实用程序函数将数组复制到新数组:
public static object[] CopyTo(object[] original, int startIndex, int endIndex)
{
List<object> copied - new List<object>();
for (int i = startIndex; i <= endIndex; i++)
{
copied.Add(original[i]);
}
return copied.ToArray();
}
我希望能够这样称呼它:
int[] newThing = CopyTo(new int[] { 10, 9, 8, 7, 6 }, 2, 4);
编译器错误说cannot convert from int[] to object[]
。 这是意料之中的,因为我的CopyTo
函数特别想要一个对象数组,而不是整数数组。
如何更改 CopyTo 的声明,以便它动态接受并返回任何类型的数组? 我相信泛型是这样(虽然我不太熟悉这个),所以我尝试了:
public static T[] CopyTo(T[] original, int startIndex......)
但编译器不会将 T 识别为类型。
要使其通用,请使用以下代码:
public static T[] CopyTo<T>(T[] original, int startIndex, int endIndex)
{
List<T> copied = new List<T>();
for (int i = startIndex; i <= endIndex; i++)
{
copied.Add(original[i]);
}
return copied.ToArray();
}
编辑:
值得一提的是,您也可以在不创建List<T>
并将列表作为数组返回的情况下执行此操作。只需创建一个数组(长度等于所需元素的数量)并填充它:
public static T[] CopyTo<T>(T[] original, int startIndex, int endIndex)
{
int count = (endIndex - startIndex) + 1;
int index = 0;
T[] copied = new T[count];
for (int i = startIndex; i <= endIndex; i++)
copied[index++] = original[i];
return copied;
}
您还可以为其创建一个扩展方法:
public static class Extensions
{
public static T[] CopyTo<T>(this T[] source, int start, int end)
{
int count = (end - start) + 1;
int index = 0;
T[] copied = new T[count];
for (int i = start; i <= end; i++)
copied[index++] = source[i];
return copied;
}
}
现在你可以这样称呼它:
var original = new int[] { 10, 9, 8, 7, 6 };
var newThing = original.CopyTo(0, 2);
或者对于字符串数组:
var strOrig = "one.two.three.four.five.six.seven".Split('.');
var strNew = strOrig.CopyTo(2, 5);
你不需要编写自己的函数,.NET Framework 已经内置了所有内容。您有两种选择:
-
Array.Copy(sourceArray, srcStartIndex, targetArray, tgtStartIndex, srcNumberOfElements);
-
sourceArray.CopyTo(targetArray, tgtStartIndex);
我将首先用一些示例来解释它们,最后我将它放在一个函数中
public static T[] CopyFromArray<T>(this T[] sourceArray, int startIndex, int endIndex)
正如您在问题中要求的那样(CopyTo 已被 .NET 保留,因此我将其重命名为 CopyFromArray)。
请注意,sourceArray
和 targetArray
是任何类型的数组; srcStartIndex
是要从中复制的sourceArray
的起始索引,tgtStartIndex
是要复制到的targetArray
的开始索引,srcNumberOfElements
是要从源数组复制的元素数。
目标数组必须足够大才能将所有元素复制到其中,否则会出现错误。源数组的元素直接复制到目标数组中("原位"),这就是为什么没有从函数返回任何数据的原因(返回类型为 void
)。
请看这个例子:
void Main()
{
var target = new int[20];
var srcStart=1; var tgtStart=3; var srcElements=3;
Array.Copy((new int[] { 1,2,3,4,5,6,7,8,9 }), srcStart,
target, tgtStart, srcElements);
Console.WriteLine(string.Join(",", target));
}
它工作正常并返回:
0,0,0,2,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
请注意,srcStart
指定源数组中的索引,从中开始复制,而tgtStart
指定目标数组中开始插入的索引,最后,srcElements
指定要复制的元素数。
请注意,还有一个更简单的版本,即 .CopyTo
方法。它的工作原理如下:
void Main()
{
var target = new int[20]; var tgtStart = 3;
(new int[] { 1,2,3,4,5,6,7,8,9 }).CopyTo(target, tgtStart);
Console.WriteLine(string.Join(",", target));
}
它返回:
0,0,0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,0,0,0,0
第二个参数指定应插入数据的位置的索引(就像上一个示例中的tgtStart
一样),这就是为什么前 3 个元素为 0。
您也可以将其与其他数据类型一起使用,例如:
var target = new string[20];
(new string[] { "abc", "def", "ghi" }).CopyTo(target, 3);
以同样的方式工作。
<小时 />谈到你的问题,你可以使用我到目前为止给你的信息来组合你自己的泛型扩展方法,如下所示:
void Main()
{
int[] newThing1 = (new int[] { 10, 9, 8, 7, 6 }).CopyFromArray(2, 4);
newThing1.Dump();
string[] newThing2 = (new string[] { "A", "B", "C", "D"}).CopyFromArray(1, 3);
newThing2.Dump();
}
public static class Extensions
{
public static T[] CopyFromArray<T>(this T[] sourceArray, int startIndex, int endIndex)
{
int numberOfElements = endIndex - startIndex + 1;
var targetArray = new T[numberOfElements];
Array.Copy(sourceArray, startIndex, targetArray, 0, numberOfElements);
return targetArray;
}
}
试试这个:
public static T[] CopyTo<T>(T[] original, int startIndex, int endIndex)
{
List<T> copied = new List<T>();
for (int i = startIndex; i < endIndex; i++)
{
copied.Add(original[i]);
}
return copied.ToArray();
}