2009-06-23 10 views
13

Esta es una posibilidad muy remota, ya sé ...¿Usar Linq para ejecutar un método en una colección de objetos?

Digamos que tengo una colección

List<MyClass> objects; 

y quiero correr el mismo método en todos los objetos de la colección, con o sin un retorno valor. Antes de LINQ habría dicho:

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)); 
} 

me habría amor a ser capaz de hacer algo como esto:

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))); 

no he encontrado nada que pueda hacer esto. ¿Hay tal cosa?

Si no hay nada genérica como que he planteado anteriormente, al menos tal vez hay una manera de hacerlo para los fines que estoy trabajando ahora: Tengo una colección de un objeto que tiene una clase contenedora:

class WrapperClass { 
    private WrappedClass wrapped; 
    public WrapperClass(WrappedClass wc) { 
    this.wrapped = wc; 
    } 
} 

Mi código tiene una colección List<WrappedClass> objects y quiero convertir eso a un List<WrapperClass>. ¿Hay alguna manera inteligente LINQ de hacer esto, sin hacer la tediosa

List<WrapperClass> result = new List<WrapperClass>(); 
foreach (WrappedClass obj in objects) 
    results.Add(new WrapperClass(obj)); 

Gracias ...

Respuesta

17

quiso;

results.AddRange(objects.Select(obj => ApplyFormula(obj))); 

hacer?

o (simple)

var results = objects.Select(obj => ApplyFormula(obj)).ToList(); 
+1

+1 Me gusta el segundo mejor :) –

+1

Dios mío, fue así de simple? ¡Maravilloso! ¡ME ENCANTA LINQ! –

4

creo que el método de extensión Select() puede hacer lo que está buscando:

objects.Select(obj => obj.MyMethod()).ToList(); // produces List<Result> 

objects.Select(obj => ApplyFormula(obj)).ToList(); // produces List<int> 

Lo mismo para el último caso:

objects.Select(obj => new WrapperClass(obj)).ToList(); 

Si tiene un método void que desea llamar, aquí hay un truco que puede usar con IEnumerable, que no tiene una extensión ForEach(), para crear un comportamiento similar sin mucho esfuerzo.

objects.Select(obj => { obj.SomeVoidMethod(); false; }).Count(); 

El Select() producirá una secuencia de [false] valores después de invocar SomeVoidMethod() en cada [obj] en la secuencia de objetos. Como el Select() usa la ejecución diferida, llamamos a la extensión Count() para forzar la evaluación de cada elemento en la secuencia. Funciona bastante bien cuando quieres algo así como un comportamiento ForEach().

1

El compilador de C# mapea una selección LINQ sobre el método de extensión .Select, definido sobre IEnumerable (o IQueryable que ignoraremos aquí). En realidad, ese método .Select es exactamente el tipo de función de proyección que buscas.

LBushkin es correcta, pero en realidad se puede utilizar la sintaxis de LINQ, así ...

var query = from o in objects 
    select o.MyMethod(); 
2

Si el método MyMethod que desea aplicar devuelve un objeto de tipo T entonces usted puede obtener una IEnumerable<T> de la resultado del método a través de:

var results = objects.Select(o => o.MyMethod()); 

Si el método MyMethod que desea aplicar el tipo tiene void volver entonces se puede aplicar el método a través de:

objects.ForEach(o => o.MyMethod()); 

Esto supone que objects es de tipo genérico List<>. Si todo lo que tiene es IEnumerable<>, entonces puede roll your ownForEach método de extensión o aplicar objects.ToList() primero y usar la sintaxis anterior.

0

También puede ejecutar un método personalizado con el de morelinq library

Por ejemplo, si tiene una propiedad de texto en sus MiClase que se necesitaba cambiar en tiempo de ejecución utilizando un método en la misma clase maravillosa Jon Skeet:

objects = objects.Pipe<MyClass>(class => class.Text = class.UpdateText()).ToList(); 

Este método ahora se implementará en cada objeto en su lista. Me encanta máslinq!

Cuestiones relacionadas