c #: Разве не Where (), OrderBy () и Select () из Enumerable Class должны принимать тип делегата, лямбда-выражение или анонимный тип в качестве параметра - PullRequest
3 голосов
/ 08 октября 2019

У меня есть вопрос. Смотрите два блока кода. Разве Where(), OrderBy() и Select() из IEnumerable Класс не должен принимать тип делегата, лямбда-выражение или анонимный тип в качестве параметра. Если да, то как QueryOverStringWithRawDelegate() дал те же результаты, что и QueryOverStringsWithExtensionMethods()?

void QueryOverStringsWithExtensionMethods()
{
    // Assume we have an array of strings
    string[] currentVideoGames = { "Morrowind", "Uncharted 2", "Fallout 3", "Daxter", "Bio Shock 4" };

    IEnumerable<string> subset = currentVideoGames.Where(game => game.Contains(" ")).OrderBy(game => game).Select(delegate (string game) { return game; });

    Console.WriteLine("Query Over Strings With Extension Method");
    foreach (var s in subset)
    {
        Console.WriteLine("Items: {0}", s);
    }
}

и

void QueryStringsWithRawDelegates()
{
    // Assume we have an array of strings
    string[] currentVideoGames = { "Morrowind", "Uncharted 2", "Fallout 3", "Daxter", "Bio Shock 4" };


    var subset = currentVideoGames.Where(Filter).OrderBy(ProcessItems).Select(ProcessItems);

    foreach (var s in subset)
    {
        Console.WriteLine("Items: {0}", s);
    }

    string ProcessItems(string game)
    {
        return game;
    }
    bool Filter(string game)
    {
        return game.Contains(" ");
    }
}

Спасибо за вашу помощь!

Ответы [ 2 ]

4 голосов
/ 08 октября 2019
currentVideoGames.Where(Filter)

это просто сокращение для:

currentVideoGames.Where(new Func<string, bool>(Filter))

То есть компилятор видит, что у вас есть метод, который принимает тип делегата Func<string, bool>, он видит, что вы его передаетеметод с сигнатурой bool Filter(string) (строго, группа методов с одной или несколькими перегрузками, одна из которых имеет достаточно близкую сигнатуру), и он автоматически вставляет код для создания экземпляра нового делегата.

Эта же языковая функция позволяет писать такие вещи, как:

SomeEvent += Handler;

вместо:

SomeEvent += new EventHandler(Handler);

См. Это на SharpLab .


Аналогично:

currentVideoGames.Where(game => game.Contains(" "))

- это сокращение от:

currentVideoGames.Where(new Func<string, bool>(CompilerGeneratedFunction))

, где CompilerGeneratedFunction будет выглядеть примерно так:

bool CompilerGeneratedFunction(string x)
{
    return x.Contains(" ");
}

Смотрите это на SharpLab . Случается, что компилятор помещает CompilerGeneratedFunction (который он назвал <M>b__0_0) в новый внутренний класс, и он кэширует Func<string, bool>, который он создает для повышения производительности.

0 голосов
/ 08 октября 2019

Нет, как вы заметили, это не ошибка. Компилятор преобразует группы методов с соответствующими сигнатурами в соответствующие типы Func <>.

...