C#:Func <t,tresult =“”>用于泛型方法</t,>

时间:2010-05-14 16:41:52

标签: c# .net generics

可以创建引用通用方法的Func object吗?像LINQ OrderBy

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

6 个答案:

答案 0 :(得分:20)

如果我理解正确,你会问你是否可以在匿名方法中引用泛型方法。

答案是肯定的。

例如,假设您希望某些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 :(得分:4)

是的,但这取决于上下文 - 如果你已经在使用泛型,只需在上下文中使用T /如果没有,那么你已经知道了特定的类型。在后面,如果你需要在一个方法上重用一点逻辑,你可能已经将它移到一个方法中了,所以就像我下面的第二个例子一样。

2个样本:

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

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

答案 2 :(得分:0)

这样的东西?

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

成功编译,你可以将任何函数分配给Nullable并返回一个字符串。

答案 3 :(得分:0)

是的,但是您需要指定类型参数

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

其中

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

如果没有类型参数

,它将无法工作

答案 4 :(得分: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的扩展方法。

答案 5 :(得分: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>;
    }
}

此外,在OrderBy中,它实际上不是通用委托。这是变量的声明。当给出函数时,可以从中推断出类型。