Я долго пытался найти «чистый» шаблон для обработки .SelectMany
с анонимными типами, когда вы не всегда хотите вернуть результат. Мой наиболее распространенный случай использования выглядит так:SelectMany Anonymous Type и Skip Iterations
- У нас есть список клиентов, с которыми я хочу вести отчет.
- Данные каждого пользователя находятся в отдельной базе данных, поэтому я делаю параллель
.SelectMany
- В каждом выражении лямбда я собираю результаты для клиента в отношении окончательного отчета.
- Если конкретный клиент должен быть пропущен, мне нужно вернуть пустой список.
- Я часто использую их для быстрой отчетности, поэтому предпочитаю анонимный тип.
Например, логика может выглядеть примерно так:
//c is a customer
var context = GetContextForCustomer(c);
// look up some data, myData using the context connection
if (someCondition)
return myData.Select(x => new { CustomerID = c, X1 = x.x1, X2 = x.x2 });
else
return null;
Это может быть реализовано как Еогеасп заявление:
var results = new List<WhatType?>();
foreach (var c in customers) {
var context = GetContextForCustomer(c);
if (someCondition)
results.AddRange(myData.Select(x => new { CustomerID = c, X1 = x.x1, X2 = x.x2 }));
}
Или это может быть реализовано с .SelectMany
, который предварительно отфильтрованный с помощью .Where
:
customers
.Where(c => someCondition)
.AsParallel()
.SelectMany(c => {
var context = GetContextForCustomer(c);
return myData.Select(x => new { CustomerID = c, X1 = x.x1, X2 = x.x2 });
})
.ToList();
Существуют проблемы с обоими из этих подходов. Решение foreach
требует инициализации List
для хранения результатов, и вы должны определить тип. .SelectMany
с .Where
часто непрактичен, поскольку логика для someCondition
довольно сложна и зависит от некоторых поисков данных. Таким образом, мое идеальное решение будет выглядеть примерно так:
customers
.AsParallel()
.SelectMany(c => {
var context = GetContextForCustomer(c);
if (someCondition)
return myData.Select(x => new { CustomerID = c, X1 = x.x1, X2 = x.x2 });
else
continue? return null? return empty list?
})
.ToList();
Что я положил в else
линии, чтобы пропустить возвращаемое значение? Ни одно из решений я не могу придумать с работой или идеальны:
continue
не компилируется, потому что это не является активнымforeach
петляreturn null
вызываетNRE
return
пустой список требует, чтобы я инициализировать список анонимного типа.
Есть ли способ выполнить вышеизложенное, что является чистым, простым и аккуратным и удовлетворяет всем моим (придирчивым) требованиям?
Это вызовет множество динамических вызовов и, в свою очередь, отражение. По производительности, это не самый лучший вариант. – Athari
Хорошая точка. Но он также говорит, что он просто нуждается в этом, чтобы создать несколько быстрых отчетов. –
Мне нравится это решение, лучшее, потому что оно короткое и не требует каких-либо специальных методов расширения. Я попробовал «Enumerable.Empty()», но не смог определить тип, без ''. Благодаря!! –
mellamokb