Ответ 1
Будет:
results.AddRange(objects.Select(obj => ApplyFormula(obj)));
делать?
или (проще)
var results = objects.Select(obj => ApplyFormula(obj)).ToList();
Это длинный выстрел, я знаю...
Скажем, у меня есть коллекция
List<MyClass> objects;
и я хочу запустить тот же метод для каждого объекта в коллекции с возвращаемым значением или без него. До Linq я бы сказал:
List<ReturnType> results = new List<ReturnType>();
List<int> FormulaResults = new List<int>();
foreach (MyClass obj in objects) {
results.Add(obj.MyMethod());
FormulaResults.Add(ApplyFormula(obj));
}
Я бы люблю, чтобы иметь возможность сделать что-то вроде этого:
List<ReturnType> results = new List<ReturnType>();
results.AddRange(objects.Execute(obj => obj.MyMethod()));
// obviously .Execute() above is fictitious
List<int> FormulaResults = new List<int>();
FormulaResults.AddRange(objects.Execute(obj => ApplyFormula(obj)));
Я не нашел ничего, что сделает это. Есть ли такая вещь?
Если нет ничего общего, как я уже говорил выше, по крайней мере, возможно, есть способ сделать это для целей, над которыми я сейчас работаю: у меня есть коллекция одного объекта, который имеет класс-оболочку:
class WrapperClass {
private WrappedClass wrapped;
public WrapperClass(WrappedClass wc) {
this.wrapped = wc;
}
}
В моем коде есть коллекция List<WrappedClass> objects
, и я хочу преобразовать ее в List<WrapperClass>
. Есть ли какой-то умный способ Linq сделать это, не выполняя утомительный
List<WrapperClass> result = new List<WrapperClass>();
foreach (WrappedClass obj in objects)
results.Add(new WrapperClass(obj));
Спасибо...
Будет:
results.AddRange(objects.Select(obj => ApplyFormula(obj)));
делать?
или (проще)
var results = objects.Select(obj => ApplyFormula(obj)).ToList();
Я думаю, что метод расширения Select() может делать то, что вы ищете:
objects.Select( obj => obj.MyMethod() ).ToList(); // produces List<Result>
objects.Select( obj => ApplyFormula(obj) ).ToList(); // produces List<int>
То же самое для последнего случая:
objects.Select( obj => new WrapperClass( obj ) ).ToList();
Если у вас есть метод void
, который вы хотите вызвать, вот трюк, который вы можете использовать с IEnumerable, у которого нет расширения ForEach(), чтобы создать подобное поведение без особых усилий.
objects.Select( obj => { obj.SomeVoidMethod(); false; } ).Count();
Select()
будет вызывать последовательность [false]
значений после вызова SomeVoidMethod()
на каждом [obj]
в последовательности объектов. Поскольку Select()
использует отложенное выполнение, мы вызываем расширение Count()
, чтобы заставить каждый элемент в последовательности, подлежащей оценке. Он работает очень хорошо, когда вы хотите что-то вроде поведения ForEach()
.
Если метод MyMethod
, который вы хотите применить, возвращает объект типа T
, тогда вы можете получить IEnumerable<T>
результата метода с помощью:
var results = objects.Select(o => o.MyMethod());
Если метод MyMethod
, который вы хотите применить, имеет тип возврата void
, то вы можете применить этот метод с помощью:
objects.ForEach(o => o.MyMethod());
Это предполагает, что objects
имеет общий тип List<>
. Если все, что у вас есть, это IEnumerable<>
, вы можете перевернуть свой собственный ForEach
метод расширения или применить сначала objects.ToList()
и использовать выше синтаксис.
Компилятор С# отображает выбор LINQ на метод .Select extension, определенный над IEnumerable (или IQueryable, который мы здесь проигнорируем). Фактически этот метод .Select - это именно тот вид функции проецирования, который вы после.
LBushkin корректен, но вы также можете использовать синтаксис LINQ...
var query = from o in objects
select o.MyMethod();
http://www.hookedonlinq.com/UpdateOperator.ashx имеет расширенный метод обновления, который вы можете использовать. Или вы можете использовать оператор select, опубликованный другими.
Вы также можете запустить собственный метод, используя замечательную библиотеку Jon Skeet morelinq
Например, если у вас было свойство text на MyClass, которое вам нужно было изменить во время выполнения, используя метод в том же классе:
objects = objects.Pipe<MyClass>(class => class.Text = class.UpdateText()).ToList();
Этот метод теперь будет реализован на каждом объекте в вашем списке. Я люблю morelinq!