【问题标题】:Why there is no SelectToArray method in System.Linq.Enumerable为什么 System.Linq.Enumerable 中没有 SelectToArray 方法
【发布时间】:2013-11-22 05:51:51
【问题描述】:

所以我想问:为什么我们只有返回可枚举的选择器?例如,我经常遇到的情况,当我必须修改数组的每个值时,例如:

int[] a = {1,2,3,4,5};
a = a.Select(x=>x*2).ToArray();

所以在这里我们得到了一个可枚举的,只有在它之后我们才能将它转换回数组。 我们可以尝试使用 Array.ForEach,但前提是我们可以修改源。但是如果我们有引用类型数组并且不能修改它们,我们无论如何都应该写这样的东西

SomeClass[] a = FillSomeClassArray();
SomeClass[] b = a.Select(x=> ((SomeClass)x.Clone()).Modify()).ToArray();

在我的情况下,我正在使用我自己的课程

public static class CollectionHelper
{
    public static TResult[] SelectToArray<T, TResult>(this ICollection<T> source, Func<T, TResult> selector)
    {
        if (source == null)
            throw new ArgumentNullException("source");
        if (selector == null)
            throw new ArgumentNullException("selector");
        var result = new TResult[source.Count];
        int i = 0;
        foreach (T t in source)
        {
            result[i] = selector(t);
            i++;
        }
        return result;
    }
}

这里我们没有双重转换,当我们没有谓词时,我们知道结果的长度,我们应该使用这个信息。我知道 MS 不应该代替我做所有的工作,但它的功能标准已经足够了。

【问题讨论】:

  • 顺便说一句,有 ToList().ForEach()
  • 我想从源中获取一个数组,只调用一个方法。 ToList().ForEach 不是更好,那么简单 Select.ToArray() 等等

标签: c# .net arrays linq collections


【解决方案1】:

SelectToArray 添加到框架的最大问题是一致性。如果添加SelectToArray,还应添加以下各项:

  • CastToArray&lt;T&gt;
  • ConcatToArray&lt;T&gt;
  • RepeatToArray&lt;T&gt;
  • ReverseToArray&lt;T&gt;
  • SkipToArray&lt;T&gt;
  • OfTypeToArray&lt;T&gt;
  • TakeToArray&lt;T&gt;

虽然我们的主题是添加新方法,但将相同的优化添加到列表有什么问题?现在我们还需要

  • SelectToList&lt;T&gt;(类似于开始这一切的那个)
  • CastToList&lt;T&gt;
  • ConcatToList&lt;T&gt;
  • ... 等等 - 我相信你明白了。

考虑到知道目标数组或目标列表的大小所带来的微不足道的节省,这样的重大重构是不切实际的。你可以用这样一个简单的方法来达到同样的效果:

static T[] CopyToArray(
    this IEnumerable<T> source
,   T[] result
,   int pos = 0
,   int? lengthOrNull = null
) {
    int length = lengthOrNull ?? result.Length;
    foreach (var item in source) {
        if (pos > length) break;
        result[pos++] = item;
    }
    return result;
}

现在调用者可以将现有的 LINQ 功能与此方法结合起来,组成上述所有XyzToArray 方法,如下所示:

IList<MyClass> data = ...
int[] res = data.Select(x => x.IntProperty).CopyToArray(new int[data.Count]);

您还可以将 LINQ 查询的结果写入现有数组的不同部分,如下所示:

IList<MyClass> data1 = ...
IList<MyClass> data2 = ...
int[] res = new int[data1.Count+data2.Count];
data1.Select(x => x.IntProperty).CopyToArray(res, 0, data1.Count);
data2.Select(x => x.IntProperty).CopyToArray(res, data1.Count, data2.Count);

【讨论】:

  • 您认为data.Select(x =&gt; x.IntProperty).CopyToArray(new int[data.Count]);data.Select(x =&gt; x.IntProperty).ToArray() 更好?关于列表的相同方法:我们可以为列表编写单个方法,然后如果我们需要一个数组,则只需返回内部列表的数组。
  • @AlexJoukovsky CopyToArray(new int[data.Count]) 肯定更快,原因与您的SelectToArray 更快。 XyzToList 方法可以共享大量实现,但您需要将这些方法的签名添加到 Enumerable,这会使已经很大的接口更加膨胀。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-24
  • 2016-10-20
  • 1970-01-01
  • 2011-07-16
  • 2015-05-01
  • 2014-03-07
  • 2011-06-12
相关资源
最近更新 更多