2010-05-14 18 views
5

可以創建Func object什麼引用通用方法?像LINQ OrderBy通用方法的C#:Func <T, TResult>

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

你可以發表你如何打算使用它的樣本?我認爲它不完全清楚你想從描述中獲得什麼。 – eglasius 2010-05-14 17:08:11

回答

19

如果我正確理解你,你問你是否可以從一個匿名方法中引用一個通用的方法。

答案是肯定的。

例如,假設您想要一些Func按排序順序返回IEnumerable<int>對象的元素(正如OrderBy<int, int>)。你可以這樣做:

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

那麼你可以使用這個Func就像任何其他:

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

輸出:

1 
2 
3 
4 
5 
6 
7 
8 
9 

在另一方面,如果你問是否有可能創建一個「通用匿名方法」,如下所示:

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

然後它取決於你的上下文。這可以在T已被聲明爲泛型類型參數的情況下完成 - 即泛型類或泛型方法中。 (見Freddy Rios的答案)不幸的是,在這種情況之外,這是非法的。

+1

謝謝丹!很好的答案+1。你的意思是不可能定義一個通用的'Func'對象? :O – SDReyes 2010-05-14 17:05:29

+2

@SDReyes:這取決於你是否有在你的範圍內定義的「T」。也就是說,例如,如果您在泛型類中工作,那麼在該類中的某個方法中,您可能會聲明一個'Func '。你也可以在一個通用的方法中做到這一點。但是,在一個不是泛型的上下文中聲明一個通用的匿名方法(即從屬於某個非泛型類的普通的非泛型方法中),恐怕是不可能的。 – 2010-05-14 17:08:20

+0

非常感謝Dan:) – SDReyes 2010-05-14 17:09:34

0

這樣的事情?

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

即編譯成功,你可以分配給任何函數,它在一個可空,並返回一個字符串。

+0

嗨CubanX !,不是真的。你引用了一個lambda函數,它接受一個可爲空的對象並返回一個字符串。我試圖引用一個泛型方法(例如接收一個TSource類型)非常感謝! – SDReyes 2010-05-14 16:50:56

0

是的,它是可能的,但你需要指定類型參數(一個或多個)

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

其中

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

它不會不帶類型參數的工作

0

我已經做了像這樣:

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

此方法已成爲C#web開發中request.form的擴展方法。

+0

嗨阿恩,謝謝你的回答。儘管如此,這不是一種通用的方法。再次感謝您 – SDReyes 2010-05-14 16:56:37

4

是的,但它取決於上下文 - 如果您已經在使用泛型,只在上下文中使用T /否則,那麼您已經知道具體的類型。在後面的內容中,如果你需要在方法上重用一些邏輯,你可能已經將它移到了一個方法中,所以就像下面的第二個例子那樣。

2個樣品:

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

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

謝謝Freddy如此清楚+1 – SDReyes 2010-05-15 15:46:51

0

我想我明白了:由於功能static TResult DoSomeStuff<T, TResult>(T obj),您可以創建一個Func<T, TResult>這樣它將引用上面的函數,用在創建引用給定無類型參數到它。
我覺得這可能是工作(歡迎你來測試它,我沒有C#在我身邊的那一刻):

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

此外,在排序依據,它實際上不是一個通用的委託。這是一個變量的聲明。當函數被賦予它時,類型可以從它推斷出來。