2009-02-19 17 views
10

Mi chiedevo se è possibile, poiché i miei 5 minuti di sperimentazione si sono rivelati infruttuosi.Funzione di identità generica da utilizzare con inferenza di tipo

speravo che sarebbe stato così facile come:

T Identity<T>(T t) { return t; } 

Ma questo non riesce a compilare su metodi generici che prendono parametri Funz. Ad esempio OrderBy. Anche specificando i parametri di tipo (che è esattamente quello che voglio evitare!), Non riesce a compilare.

Poi ho provato qualcosa che pensavo avrebbe funzionato:

Func<T, R> MakeIdentity<T, R>() 
{ 
    return (T t) => (R)(object)t; 
} 

anche no go :((questa compila quando si applica parametri di tipo, ancora una volta, non quello che voglio)

Qualcuno ha avuto fortuna mettere tali una cosa

UPDATE:? per favore non dire: x => x, lo so, è ovvio che sto chiedendo per una funzione, non è un'espressione :)

UPDATE 2: Quando I ref per identità, intendo in senso funzionale, dove la funzione restituisce semplicemente lo stesso oggetto che hai passato ad esso. È probabilmente in ogni linguaggio funzionale che ho incontrato, ma quelli non usano la digitazione statica. Mi chiedo come fare questo (se possibile) con i generici. Solo per divertimento!

UPDATE 3: Ecco una 'soluzione' parziale in base alla seconda idea:

Expression<Func<T, T>> MakeIdentity<T>() 
{ 
    return t => t; 
} 

void Foo(string[] args) 
{ 
    var qargs = args.AsQueryable(); 
    var q = qargs.OrderBy(MakeIdentity<string>()); 
    ... 
} 

Non credo che qualcosa di più di questo sarà possibile.

+0

Che cosa stai cercando di fare? –

+0

Stanco di scrivere x => x :) E mi sto solo chiedendo davvero. non ha scopo. – leppie

+0

Con C# 6.0 'myList.OrderBy (Identity);' funzionerà. – Henrik

risposta

3

L'inferenza di tipo non funziona poiché il metodo host e il metodo di immissione sono entrambi generici. Per fare questo è necessario scrivere

myList.OrderBy<int, int>(Identity); 

O

myList.OrderBy((Func<int, int>)Identity); 
1

Il problema che si verifica è che le funzioni anonime e i gruppi di metodi in C# non partecipano all'inferenza di tipo. Devono essere forniti tipi espliciti.

Ciò che si può fare è disporre delle funzioni di identità per le funzioni anonime. Esempio

Func<T> IdentityFunc1<T>(Func<T> func) { return func; } 

Non sono del tutto sicuro di ciò che si ottiene con il secondo campione. Puoi elaborare?

+1

Penso che tu capisca l'identità sbagliata. È una funzione comunemente usata nel linguaggio funzionale, che restituisce semplicemente ciò che gli dai. – leppie

+0

Penso che la tua risposta sia ancora valida, grazie :) – leppie

0

La prima opzione funziona per me:

public class Foo { 

    public Foo(Func<MyObj, MyObj> map) {... } 

} 

public class Client { 

    private static T Identity<T>(T t) { return t; } 

    public void main() { 
     var foo = new Foo(Identity); 

     var c = from f in Enumerable.Range(0, 100) select Identity(f); 
     c.ToList().ForEach(System.Console.Out.WriteLine); 
    } 
} 
2

Questo funziona per me in luoghi che ho avuto bisogno finora.

internal class IdentityFunction<TSource> 
{ 
    public static Func<TSource, TSource> Instance 
    { 
     get { return x => x; } 
    } 
} 

OrderBy(IdentityFunction<Foo>.Instance) 
Problemi correlati