C# - 返回通用数组类型

5
如果我有一个简单的实用函数,可以将一个数组复制到一个新数组中:
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);

编译器报错说“无法将int[]转换为object[]”。这是可以预料的,因为我的CopyTo函数需要一个对象数组而不是一个整数数组。
我该如何更改CopyTo的声明,以便它动态地接受和返回任何类型的数组?我相信泛型是一种方法(虽然我对此不太熟悉),因此我尝试了:
public static T[] CopyTo(T[] original, int startIndex......)

但编译器无法将T识别为一种类型。

2
你需要使用 ... CopyTo<T>(...) - Anton Gogolev
该函数已经存在于.NET框架中 - 请参见我的答案 - Matt
3个回答

9
要使其通用,请使用以下代码:

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);

2

您不需要编写自己的函数,.NET框架已经内置了所有内容。您有两个选项:

  • 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

请注意,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

第二个参数指定了数据插入的位置索引(就像前面例子中的 tgtStart 一样),这就是前三个元素为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;
    }
}

谢谢你的回答,我会查阅一下。然而,我提供的示例只是我想要做的事情的简化版本,可能会有其他功能我稍后添加。但还是谢谢你。 - Arj

1

试试这个:

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();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接