我们处理了很多数组,所以大部分 LINQ 查询都以后缀
.ToArray()
结尾。我想介绍一个 LINQ 方法的“影子”库,它直接生成数组而不是中间枚举。
static class EnumerableExtensions
{
public static R[] SelectToArray<S,R>(this S[] self, Func<S, R> func)
=> self.Select(func).ToArray();
}
然后我意识到我真的不想区分
Select()
和SelectToArray()
,所以我相应地更改了名称。然而,我最终会在一个永远不会使用原始版本的循环调用中结束,因为我已经用我的扩展方法隐藏了它。
我能想到的最好办法是欺骗 C# 相信我仍在处理
IEnumerable<S>
而不是 S[]
.
static class EnumerableExtensions
{
public static R[] SelectToArray<S,R>(this S[] self, Func<S, R> func)
=> self.AsEnumerable().Select(func).ToArray();
}
我的烦恼是双重的。首先,像这样转换数组似乎很可疑,使它成为可枚举的,然后返回数组。这对我来说是代码的味道,但我无法确定。
其次,假设上面没问题并且可以使用,我如何启用C#来了解我在以下示例中寻找的版本? (我是显式类型的坚定拥护者,但知道它是自以为是的,我希望能够向不同意我观点的人解释。)
IEnumerable<string> thisIsEnumerable = array.Select(a => a.Property);
string[] thisIsArray = array.Select(a => a.Property);
var whatIsThis = array.Select(a => a.Property);
我知道它会是什么,但我如何使
var
'ed 的东西呈现原始类型(如果我们消除扩展方法,这将生效)?
我可以建议一个替代方案,它显示出明确的意图(易于猜测的返回类型)并且不会混淆众所周知的 LINQ 函数:
static class EnumerableExtensions
{
public static R[] ToArray<S,R>(this IEnumerable<S> self, Func<S, R> selector)
=> self.Select(selector).ToArray();
}
用法:
var names = peopleCollection.ToArray(p => p.Name);
除非你的问题比目前描述的更深,这似乎通过删除相同数量的(8)个字符(
Select + ()
)来解决问题,每次你需要一个Select()
然后是一个ToArray()
调用
Array.ConvertAll
作为您的扩展方法,这比使用 Select...ToArray
更有效,因为它知道结果数组的大小:
public static class EnumerableExtensions
{
public static TResult[] SelectToArray<TInput, TResult>(this TInput[] array, Func<TInput, TResult> converter)
{
return Array.ConvertAll<TInput, TResult>(array, new Converter<TInput, TResult>(converter));
}
}
样品:
int[] inputArray = {1,2,3};
string[] resultArray = inputArray.SelectToArray(i => i.ToString());
你也可以为列表提供一个:
public static List<TResult> SelectToList<TInput, TResult>(this List<TInput> list, Func<TInput, TResult> converter)
{
return list.ConvertAll<TResult>(new Converter<TInput, TResult>(converter));
}