关于效率,有没有人知道编译器是否聪明到可以而不是在下面的代码中为循环的每次迭代创建包含1, 3, 5的数组?
var foo = new List<int> { 1, 2, 3, 4, 5 };
foo.RemoveAll(i => new[] { 1, 3, 5 }.Contains(i));我更喜欢它的可读性,但不是为了性能。
发布于 2019-04-05 08:51:41
答案是否定的--它没有优化数组的分配
基本上,每次调用谓词时,它都会检查编译器生成的类,并初始化一个新数组来调用Contains (如您所见的这里)。
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static Predicate<int> <>9__0_0;
internal bool <M>b__0_0(int i)
{
// bam!
int[] obj = new int[3];
RuntimeHelpers.InitializeArray(obj, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
return Enumerable.Contains(obj, i);
}
}发布于 2019-04-05 09:01:56
正如@Michael已经写过的,这看起来是不可能的。
我同意,您的被质疑的代码具有良好的可读性,其中包含了RemoveAll方法中的列表。但只有一次实例,我有三个想法去做:
int[] a = null;
foo.RemoveAll(i => (a ?? (a = new[] { 1, 3, 5 })).Contains(i));这实际上是你的,几乎不需要一个外部变量。
foo = foo.Except(new[] { 1, 3, 5 }).ToList();这实际上是一个很好的解决方案,使用Linq。
new List<int>{1, 3, 5}.ForEach(x => foo.Remove(x));
new[] {1, 3, 5}.Iterate(x => foo.Remove(x));这是我会做的事。在neary中,我的所有代码都有我的扩展方法“迭代”,以避免预期的需要。而且,我也不想一直用"toList“来做.ForEach(..)
static class Extensions
{
public static void Iterate<TSource>(this IEnumerable<TSource> source, Action<TSource> action)
{
foreach (var item in source)
{
action.Invoke(item);
}
}
}发布于 2019-04-05 09:40:02
既然编译器没有那么聪明,我们就必须比他聪明。
var foo = new List<int> { 1, 2, 3, 4, 5 };
var bar = new HashSet<int>() { 1, 3, 5 };
foo.RemoveAll(i => bar.Contains(i));https://stackoverflow.com/questions/55531327
复制相似问题