在 LINQ 中正确使用自定义 Select() 扩展方法

问题描述 投票:0回答:2

我们处理了很多数组,所以大部分 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 的东西呈现原始类型(如果我们消除扩展方法,这将生效)?

c# linq select extension-methods
2个回答
1
投票

我可以建议一个替代方案,它显示出明确的意图(易于猜测的返回类型)并且不会混淆众所周知的 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()
调用


0
投票

对于它的价值,您可以使用

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));
}
© www.soinside.com 2019 - 2024. All rights reserved.