En un ejemplo artificial, tengo una instancia que admite la siguiente interfaz:
public interface ISelector<L, R> { R Select(L value); } Ahora, considero 2 formas de llamar a IEnumerable.Select<L, R>(Func<L, R>) :
IEnumerable<L> l; ISelector<L, R> selector; IEnumerable<R> r; r = l.Select(v => selector.Select(v)); // 1 r = l.Select(selector.Select); // 2 La forma 1 captura la referencia al selector de la variable en un cierre, y este cierre mantendrá esta referencia independientemente del alcance del selector de variables. Por lo tanto, el selector de variables puede quedar fuera del alcance y se puede llamar a r.ToList() después de que el selector de variables quede fuera del alcance.
Sin embargo, no estoy seguro de cómo entender la forma 2: ¿Cómo se asigna y captura ISelector<L, R>.Select ? ¿Y puede el selector de variables quedar fuera del alcance y se puede llamar a r.ToList() después de que el selector de variables haya quedado fuera del alcance?
En cuanto a la legibilidad, prefiero la forma 2, pero antes de usarla, me gustaría comprender primero la vida útil de las partes capturadas y recolectadas como basura.
En el segundo ejemplo, selector.Select se interpreta como abreviatura de una nueva instancia de delegado donde selector es el destino e ISelector<L, R>.Select .Select es MethodInfo . Como tal, se puede acceder al selector a través de la instancia del delegado, por lo tanto: siempre que se pueda acceder al delegado, se puede acceder al objeto del selector y no se puede recopilar. Así que sí, puede llamar a ToList() de forma segura en cualquier momento.
Específicamente, aquí , vemos para var projected l.Select(obj.Select);
// l. [push 1] IL_000d: ldloc.1 // obj. [push 1] IL_000e: ldloc.0 // Select [push 1] IL_000f: ldftn instance string X::Select(int32) // new Func<int,string>([pop 2, push 1]) IL_0015: newobj instance void class [System.Private.CoreLib]System.Func`2<int32, string>::.ctor(object, native int) // Enumerable.Select<int,string>([pop 2, push 1]) IL_001a: call class [System.Private.CoreLib]System.Collections.Generic.IEnumerable`1<!!1> [System.Linq]System.Linq.Enumerable::Select<int32, string>(class [System.Private.CoreLib]System.Collections.Generic.IEnumerable`1<!!0>, class [System.Private.CoreLib]System.Func`2<!!0, !!1>) // projected=[pop 1] IL_001f: stloc.2cual es el delegado