2010-05-14 13 views
5

¿Es posible crear un Func object qué hace referencia a un método genérico? como el LINQ OrderBy:C#: Func <T, TResult> para métodos genéricos

public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
    this IEnumerable<TSource> source, 
    Func<TSource, TKey> keySelector 
) 
+0

¿puede publicar una muestra de cómo piensa utilizarlo? Creo que no está exactamente claro qué quieres lograr con la descripción. – eglasius

Respuesta

19

Si te entiendo correctamente, estás preguntando si puedes hacer referencia a un método genérico desde un método anónimo.

La respuesta es sí.

Por ejemplo, supongamos que quiere un Func que devuelve los elementos de un objeto IEnumerable<int> en orden ordenado (precisamente como OrderBy<int, int>). Usted puede hacer esto:

Func<IEnumerable<int>, Func<int, int>, IOrderedEnumerable<int>> orderByFunc = 
    System.Linq.Enumerable.OrderBy<int, int>; 

Posteriormente, se podría utilizar este Func al igual que cualquier otra:

int[] ints = new int[] { 1, 3, 5, 4, 7, 2, 6, 9, 8 }; 

// here you're really calling OrderBy<int, int> -- 
// you've just stored its address in a variable of type Func<...> 
foreach (int i in orderByFunc(ints, x => x)) 
    Console.WriteLine(i); 

Salida:

1 
2 
3 
4 
5 
6 
7 
8 
9 

Por otro lado, si estás preguntando si es posible crear un "método anónimo genérico", como este:

Func<T> getDefault<T> =() => default(T); 

Luego depende de su contexto. Esto se puede hacer desde un contexto en el que T ya está declarado como un parámetro de tipo genérico, es decir, dentro de una clase genérica o método genérico. (Véase la respuesta de Freddy Ríos.) Fuera de ese contexto, desafortunadamente, es ilegal.

+1

Gracias Dan! buena respuesta +1. ¿Quiere decir que no es posible definir un objeto 'Func' genérico? : O – SDReyes

+2

@SDReyes: eso depende de si tiene o no una 'T' definida dentro de su alcance. Es decir, si está trabajando dentro de una clase genérica, por ejemplo, dentro de un método en esa clase, es posible que pueda declarar un 'Func '. También podría hacer esto dentro de un método genérico. Pero, me temo, no es posible declarar un método anónimo genérico en un contexto que ya no es genérico (es decir, desde dentro de cualquier método simple no genérico que pertenezca a alguna clase no genérica). –

+0

Muchas gracias Dan:) – SDReyes

0

¿Alló como esto?

Func<Nullable<int>, string> myFunc = c => c.HasValue ? c.ToString() : "null";

que compila correctamente y puede asignar cualquier función a la que se lleva en un anulable y devuelve una cadena.

+0

¡Hola CubanX !, en realidad no. estás haciendo referencia a un lambda que toma un objeto que admite nulos y devuelve una cadena. Estoy tratando de hacer referencia a un método genérico (que recibe un tipo de TSource, por ejemplo) ¡Muchas gracias! – SDReyes

0

Sí, es posible, sino que tendrá que especificar el argumento (s) Tipo de

func<int> f = myClass.returnsT<int>; 

donde

class myClass 
{ 
    T returnsT<T>() 
    {...} 
} 

no va a funcionar sin los argumentos de tipo

0

que he hecho algo como esto:

public static class Helper{ 

public static IEnumerable<KeyValuePair<string, string>> ToPairs(this NameValueCollection Form) 
     { 
      return Form.AllKeys.Cast<string>() 
       .Select(key => new KeyValuePair<string, string>(key, Form[key])); 
     } 
} 

Donde este método se ha convertido en un método de extensión para request.form en C# web development.

+0

Hola, Arne, gracias por tu respuesta. no obstante, este no es un método genérico. gracias de nuevo – SDReyes

4

Sí, pero depende del contexto: si ya está trabajando con genéricos, simplemente use la T en el contexto/si no, entonces ya conoce el tipo específico. Más tarde, si necesita reutilizar un poco de lógica en un método, probablemente ya se beneficiaría de pasarlo a un método, así que haga clic en el segundo ejemplo a continuación.

2 muestras:

public T Something<T>() { 
    Func<T> someFunc =() => { return default(T); }; 
    return someFunc(); 
} 

public Func<T> GetDefaultCreator<T>() { 
    return() => { return default(T); }; 
} 
+0

Gracias Freddy tan claro +1 – SDReyes

0

Creo que lo entiendo: Dada la función static TResult DoSomeStuff<T, TResult>(T obj), se puede crear un tal Func<T, TResult> que va a hacer referencia a la función anterior, sin parámetros tipo dado en la creación de la referencia lo.
creo que esto podría funcionar (eres bienvenido a probarlo, no tengo C# cerca de mí en este momento):

class UselessClass<T, TResult> 
{ 
    // If it's a static method, this is fine: 
    public Func<T, TResult> DaFunc = RelevantClass.DoSomeStuff<T, TResult>; 
    // If not, something like this is needed: 
    public UselessClass(SomeClassWhereTheFunctionIs from) 
    { 
     DaFunc = from.DoSomeStuff<T, TResult>; 
    } 
} 

Además, en OrdenarPor, en realidad no es un delegado genérico. Es una declaración de una variable. Cuando se le asigna la función, los tipos se deducen de ella.

Cuestiones relacionadas