有人能解释一下 C# 中的 "Func<T,T>" 是什么吗?

39

我正在阅读《Pro MVC 2》一书,其中有一个关于为HtmlHelper类创建扩展方法的示例。

以下是代码示例:

public static MvcHtmlString PageLinks(this HtmlHelper html, PagingInfo pagingInfo, Func<int,string> pageUrl)
{
    //Magic here.
}

以下是使用示例:

[Test]
public void Can_Generate_Links_To_Other_Pages()
{
    //Arrange: We're going to extend the Html helper class.
    //It doesn't matter if the variable we use is null            
    HtmlHelper html = null;

    PagingInfo pagingInfo = PagingInfo(){
        CurrentPage = 2,
        TotalItems = 28,
        ItemsPerPage = 10
    };

    Func<int, String> pageUrl = i => "Page" + i;

    //Act: Here's how it should format the links.
    MvcHtmlString result = html.PageLinks(pagingInfo, pageUrl);

    //Assert:
    result.ToString().ShouldEqual(@"<a href=""Page1"">1</a><a href=""Page2"">2</a><a href=""Page3"">3</a>")           

}

编辑:已删除混淆本问题主旨的部分。

问题是:为什么示例代码使用 Func?我应该在什么情况下使用它?什么是 Func?

谢谢!


主要是想了解 Func<int, String> pageUrl = i => "Page1" + i; 这一行代码的作用。 - delete
1
我不明白。Func<T, T>与扩展方法没有任何关系。你在问什么? - BoltClock
你是指 PageLinks 的声明吗?第一个参数是 this,也就是一个扩展方法。该参数会绑定到调用中的 html 对象上。 - Pete
1
请注意:请忽略扩展方法部分,我写错了问题。我主要想了解 Func 是什么,以及为什么这个例子选择使用它。还有,我应该在什么时候使用它。我提供了这个例子,只是为了提供上下文。 - delete
注意:提到扩展方法仅是因为在MVC书中,Func首次出现在介绍它们的章节中。 - user146043
8个回答

106

一个类似于 Func<int, string> 的函数

Func<int, String> pageUrl = i => "Page" + i;

这是一个接受int作为其唯一参数并返回string的委托。在这个例子中,它接受一个名为iint参数,并返回字符串"Page" + i,它只是将i的标准字符串表示连接到字符串"Page"

通常情况下,Func<TSource, TResult>接受一个类型为TSource的参数并返回一个类型为TResult的参数。例如,

Func<string, string> toUpper = s => s.ToUpper();

那么你可以说

string upper = toUpper("hello, world!");
或者
Func<DateTime, int> month = d => d.Month;

所以你可以说

int m = month(new DateTime(3, 15, 2011));

13

Func<int, String>表示一个回调方法,它接受一个int参数并返回一个String作为结果。

下面这个表达式被称为一个lambda表达式

Func<int, String> pageUrl = i => "Page" + i;

扩展后的结果大致如下:

Func<int, String> pageUrl = delegate(int i)
{
    return "Page" + i;
}

3
你所询问的Func<int, string>是一个称为lambda表达式的东西。
Func<int, String> pageUrl = i => "Page" + i;

这行代码可以描述为一个函数,它接受一个整数参数 (i) 并返回一个字符串 "Page" + i;

可以重写为:

delegate(int i)
{
    return "Page" + i;
}

能否重载委托,比如输入是一个泛型 T,其中 T:class? - Travis J

1

因为PageLinks方法是一个扩展方法

在扩展方法中,第一个参数以this关键字开头,表示它是作用于第一个参数所表示类型的扩展方法。

Func<T1,T2>是代表从类型T1到类型T2的转换的委托。因此,您的PageLinks方法将应用该转换到int,以产生string


1
好的 - 但是函数部分怎么办? - delete
请查看我的答案以获取 Func 的链接。 - user170386

1

1

我在博客中有一篇关于这个的文章。使用Func,您可以解决一些功能上的差异。阅读此处


0

创建你自己的

Func<int,string> myfunc; 

然后右键单击 Func 查看定义。您将看到它是一个委托。

public delegate TResult Func<in T, out TResult>(T arg);

0
我已经实现了一个使用Func的where()扩展方法,请看一下...
public static IEnumerable<Tsource> Where<Tsource> ( this IEnumerable<Tsource> a , Func<Tsource , bool> Method )
{

    foreach ( var data in a )
    {
        //If the lambda Expression(delegate) returns "true" Then return the Data. (use 'yield' for deferred return)
        if ( Method.Invoke ( data ) )
        {
            yield return data;
        }
    }
}

你可以像这样使用它,

        foreach ( var item in Emps.Where ( e => e.Name == "Shiv" ).Select ( e1 => e1.Name ) )
        {
            Console.WriteLine ( item );
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接