В чем разница между вызовом Func по-разному в том, где

private void MainForm_Load(object sender, EventArgs e)
{
     Func<int, bool> f = funn;
     var list = new List<int>();
     list.Add(32);
     list.Add(1);
     list.Add(2);
     list.Add(3);
     MessageBox.Show(list.Where(f).First().ToString());//I give only f
}
private bool funn(int k)
{
        return k == 12;
}

См. аргумент предложения Where

private void MainForm_Load(object sender, EventArgs e)
{
     Func<int, bool> f = funn;
     var list = new List<int>();
     list.Add(32);
     list.Add(1);
     list.Add(2);
     list.Add(3);
     MessageBox.Show(list.Where(i=>f(i)).First().ToString());//Now I give f with i
}
private bool funn(int k)
{
        return k == 12;
}

Что ж, в чем разница между этими королем вызова метода фильтра?


person levi    schedule 19.06.2013    source источник
comment
Второй использует лямбда для вызова вашего метода, поэтому я считаю, что предложение Where в конечном итоге вызывает 2 метода (лямбда и f). Оптимизирует ли компилятор этот факт, я не знаю. Ощутимая разница заключается в том, что если у вас нет обновления 2 для Visual Studio 2012, вы не можете установить точку останова в funn и нажать ее.   -  person Matthew    schedule 19.06.2013


Ответы (1)


Для этого конкретного примера нет семантической разницы, потому что:

Where(method)

будет ожидать, что method будет иметь сигнатуру bool method(T object), где T — тип перечисляемого, и будет просто вызывать method() для каждого объекта в последовательности.

Where( item => method(item) )

делает то же самое, потому что передает каждый объект в последовательности в method().

Однако, если вам нужно (например) использовать какое-то свойство в item для выполнения теста, вы должны использовать явную лямбду.

Например, представьте, что если бы у item было свойство Text, которое вы хотели бы передать method(), вам нужно было бы сделать:

Where( item => method(item.Text) )

В этом случае method() будет иметь подпись bool method(string).

Подробнее

Причина, по которой вы можете просто использовать имя метода вместо делегата лямбда, заключается в «преобразовании групп методов».

Это подробно описано в разделе 6.6 спецификации языка C#. Проще говоря, это означает, что если метод имеет ту же сигнатуру, что и делегат, он может быть автоматически преобразован в такой тип делегата.

Из спецификации:

Существует неявное преобразование (§6.1) из группы методов (§7.1) в совместимый тип делегата. Учитывая тип делегата D и выражение E, которое классифицируется как группа методов, существует неявное преобразование из E в D, если E содержит по крайней мере один метод, применимый в своей нормальной форме (§7.5.3.1) к построенному списку аргументов. с помощью типов параметров и модификаторов D, как описано ниже.

(И далее это продолжается гораздо подробнее, которые я не буду публиковать здесь!)

person Matthew Watson    schedule 19.06.2013
comment
Это не совсем так; они обрабатывают конверсии по-разному. - person SLaks; 19.06.2013
comment
@SLaks Даже для этого конкретного примера? Какое преобразование будет обрабатываться по-другому для конкретного примера в OP? Я что-то упускаю... Действительно, Resharper предлагает преобразовать вторую форму в первую. - person Matthew Watson; 19.06.2013