Может кто-нибудь объяснить, что делает C # "Func <T, T>"? - PullRequest
39 голосов
/ 15 марта 2011

Я читаю книгу 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?

Спасибо!

Ответы [ 8 ]

106 голосов
/ 15 марта 2011

A Func<int, string> подобно

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

- делегат, принимающий int в качестве единственного параметра и возвращающий string.В этом примере он принимает параметр int с именем i и возвращает строку "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 голосов
/ 15 марта 2011

Func<int, String> означает метод обратного вызова, который принимает параметр int и возвращает String в качестве результата.

Следующее выражение, известное как лямбда-выражение :

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

расширяется до чего-то вроде этого:

Func<int, String> pageUrl = delegate(int i)
{
    return "Page" + i;
}
3 голосов
/ 15 марта 2011

Строка Func<int, string>, о которой вы спрашиваете, называется лямбда-выражением.

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

Эта строка может быть описана как функция, которая принимает параметр int (i) и возвращаетстрока "Page" + i;

Может быть переписана как:

delegate(int i)
{
    return "Page" + i;
}
1 голос
/ 29 мая 2014

Пост в блоге об этом.Используя Func, вы можете устранить некоторые функциональные несоответствия.Читайте здесь .

1 голос
/ 15 марта 2011

Func<T, TResult>: инкапсулирует метод с одним параметром и возвращает значение типа, указанного параметром TResult. См. Эту страницу для более подробной информации и примеров. : -)

1 голос
/ 15 марта 2011

Поскольку метод PageLinks является методом расширения .

В методе расширения первый параметр начинается с этого ключевого слова, чтобы указать, что это метод расширения для типа, представленного какпервый параметр.

Func<T1, T2> - это делегат, представляющий преобразование из типа T1 в тип T2.Таким образом, ваш PageLinks метод будет применять это преобразование к int для получения string.

0 голосов
/ 13 ноября 2014

Создайте свой собственный

Func<int,string> myfunc; 

, затем щелкните правой кнопкой мыши Func, чтобы просмотреть определение.Вы увидите, что это делегат под

public delegate TResult Func<in T, out TResult>(T arg);
0 голосов
/ 07 апреля 2014

Я реализовал метод расширения where () с использованием Func, пожалуйста, посмотрите ...

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