【问题标题】:C# - Return generic array typeC# - 返回泛型数组类型
【发布时间】:2014-05-16 15:42:47
【问题描述】:

如果我有一个将数组复制到新数组的简单实用程序函数:

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 识别为类型。

【问题讨论】:

  • 你需要... CopyTo&lt;T&gt;(...
  • 该功能已经存在于 .NET 框架中 - 请参阅我的 answer

标签: c# arrays .net generics .net-core


【解决方案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();
}

编辑:

顺便提一下,您也可以在不创建List&lt;T&gt; 并将列表作为数组返回的情况下执行此操作。只需创建一个数组(长度等于所需元素的数量)并填充它:

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】:

    试试这个:

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

    【讨论】:

      【解决方案3】:

      您不需要编写自己的函数,.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)。

      注意sourceArraytargetArray 是任意类型的数组; 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),这就是前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;
          }
      }
      

      【讨论】:

      • 感谢您的回答,我会查查的。然而,我提供的示例只是我想要做的简化版本,我稍后可能会添加其他功能。不过谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-17
      • 1970-01-01
      • 1970-01-01
      • 2016-12-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多