У меня есть следующий код:Проверка работоспособности. Вкладывают ли эти вложенные. Все вызовы приравниваются к соответствующим .Where и .SelectMany звонят в LINQ?
bool b = myList
.All(x => x.MyList
.Where(y => y.MyBool)
.All(y => y.MyList
.All(z => z.MyBool)))
Является ли это функционально эквивалентно:
bool b = myList
.SelectMany(x => x.MyList)
.Where(x => x.MyBool)
.SelectMany(x => x.MyList)
.All(x => x.MyBool)
Я думаю, что это, но мой коллега бросил вызов мне, что это изменение может быть функционально отличается в некоторых (например, если какая-либо из коллекций пуста, например).
Хотя ответ да или нет, любые мнения по этому вопросу также будут оценены в отношении того, что лучше с точки зрения удобочитаемости, цикличности, временной сложности и производительности.
UPDATE:
Итак, я профилированного код, используя следующие:
static void Main(string[] args)
{
var myList = new List<A>();
for (var j = 0; j < 1000; j++)
{
var a = new A();
for (var k = 0; k < 1000; k++)
{
var b = new B {MyBool = true};
for (var l = 0; l < 1000; l++)
{
var c = new C {MyBool = true};
b.MyList.Add(c);
}
a.MyList.Add(b);
}
myList.Add(a);
}
for (var x = 0; x < 10000; x++)
{
bool b1 = Foo(myList);
}
for (var x = 0; x < 10000; x++)
{
bool b2 = Bar(myList);
}
}
private static bool Foo(List<A> myList)
{
return myList
.All(x => x.MyList
.Where(y => y.MyBool)
.All(y => y.MyList
.All(z => z.MyBool)));
}
private static bool Bar(List<A> myList)
{
return myList
.SelectMany(x => x.MyList)
.Where(x => x.MyBool)
.SelectMany(x => x.MyList)
.All(x => x.MyBool);
}
private class A
{
public List<B> MyList => new List<B>();
}
private class B
{
public bool MyBool { get; set; }
public List<C> MyList => new List<C>();
}
private class C
{
public bool MyBool { get; set; }
}
То, что я обнаружил, что второй метод (Bar
) с использованием .SelectMany
и .Where
почти 80% быстрее, чем первый метод (Foo
) с использованием вложенных вызовов .All
. Но это было только доказано на очень большом наборе данных, и фактическое время было очень маленьким. Это может иметь большее значение для меньших наборов данных, если каждый элемент вызывает запрос (например, в базу данных), который занимает больше времени, если действительно разница в производительности связана с количеством считываемых элементов. Но если разница связана с накладными расходами между считывающими элементами, а элементы считываются одинаковым количеством раз для любого метода, то я полагаю, что разница в производительности всегда будет незначительной, независимо от размера набора данных или времени чтения элемента.
Результаты ниже (из Visual Studio Performance Profiler):
Поскольку 'All' возвращает' true' для пустых множеств, они эквивалентны. Что относительно того, что лучше, это зависит от мнения или реализации. –