我希望通过转换方法将一种类型的列表转换为另一种类型,但只是有选择地(如果转换结果是否为 null(。它显示在下面的代码中。
private List<B> GetBList(List<A> aList)
{
List<B> bList = new List<B>();
foreach (A a in aList)
{
B b = GetB(a);
if (b != null)
{
bList.Add(b);
}
}
return bList;
}
private B GetB(A a)
{
if (a != null)
{
return new B();
}
return null;
}
有没有办法使用 LINQ 编写它,如下所示。以下函数的问题在于,即使转换结果为 null,它也将始终移动数据。结果必须是数组(B 的数组(,输入必须是列表(A 的列表(。
private B[] GetBList(List<A> aList)
{
return aList.Select(GetB)?.ToArray() ?? Array.Empty<A>();
}
请指教。提前感谢!
您可以使用Select(x => GetB(x))
选择这将返回转换后的对象。然后你应该用Where(x => x != null)
过滤它。然后将其转换为array
.
请注意,我在aList
之后使用了?
作为aList?.Select
,因此它将处理aList
对象null
的情况。
private B[] GetBList(List<A> aList)
{
return aList?.Select(x => GetB(x)).Where(x => x != null).ToArray() ?? Array.Empty<B>();
}
编辑如果Select(x => GetB(x))
也可以改用Select(GetB)
。
private B[] GetBList(List<A> aList)
{
return aList?.Select(GetB).Where(x => x != null).ToArray() ?? Array.Empty<B>();
}
我遇到过很多需要这样的函数的情况,因此我编写了自己的扩展方法。与此同时,我不认为我这样做赢得了任何东西,你对卡兰的回答做得很好。一方面,你不会在性能上获得任何东西,另一方面,它只会增加代码的复杂性和可读性。
但是,它对我进入 LINQ 表达式、了解后面发生的事情以及了解 IEnumerable、ICollection 等的差异有很大帮助。
为了完整性和潜在的灵感,无论如何我都会分享我的代码:
public static IEnumerable<TResult> SelectByCondition<TInput, TResult>(this IEnumerable<TInput> input, Func<TInput, TResult> selector, Func<TResult, bool> checker) {
using var enumerator = input.GetEnumerator();
while (enumerator.MoveNext()) {
var selection = selector(enumerator.Current);
if (checker(selection)) {
yield return selection;
}
}
}
在您的情况下,您可以像这样使用它:
aList?.SelectByCondition(GetB, x => x != null).ToArray() ?? Array.Empty<B>();
如果您碰巧多次遇到 null 检查的方案,以下简化可能仍然有用:
public static IEnumerable<TResult> SelectIfNotNull<TInput, TResult>(this IEnumerable<TInput> input, Func<TInput, TResult> selector) {
using var enumerator = input.GetEnumerator();
while (enumerator.MoveNext()) {
var selection = selector(enumerator.Current);
if (selection != null) {
yield return selection;
}
}
}
然后可以简化实际调用:
aList?.SelectIfNotNull(GetB).ToArray() ?? Array.Empty<B>();