C# LINQ и функционал

Это упрощенная версия того, что я использую, просто чтобы вы знали, чего я пытаюсь достичь:

public Dictionary<int, Func<int>> Magic(Dictionary<int, int> dictionary)
{
    return dictionary
        .Select(v => new
        {
            key = v.Key,
            function = new Func<int>(() => v.Value + 5)   // *
        })
        .ToDictionary(v => v.key, v => v.function);
}

Можно ли сделать линию, отмеченную звездочкой (*), короче? Потому что, когда я пытаюсь удалить избыточное (на мой взгляд) создание делегата, оно выдает ошибки:

function = () => v.Value + 5   // *

Но это не должно давать ошибок, ясно, что возвращаемый тип...

2 ответа

Решение

Вы можете сократить все это до этого:

public Dictionary<int, Func<int>> Magic(Dictionary<int, int> dictionary)
{
    return dictionary
        .ToDictionary(v => v.Key, v => (Func<int>)(() => v.Value + 5));
}

Но вам все равно нужно явно привести к Func<int>,

Единственный другой способ это:

public Dictionary<int, Func<int>> Magic(Dictionary<int, int> dictionary)
{
    return dictionary
        .ToDictionary<KeyValuePair<int, int>, int, Func<int>>(
            v => v.Key, 
            v => () => v.Value + 5);
}

Лямбда-выражения не имеют типа. Вот почему вы должны добавить компилятору некоторую информацию, чтобы определить его тип (давая им некоторый контекст).

Обратите внимание, что лямбда-выражения сами по себе не имеют типа, потому что в общей системе типов нет внутреннего понятия "лямбда-выражения". Однако иногда удобно неформально говорить о "типе" лямбда-выражения. В этих случаях тип относится к типу делегата или типу выражения, в которые преобразуется лямбда-выражение.

из лямбда-выражений (Руководство по программированию в C#)

Вы можете сделать это по типу переменной / параметра / свойства / поля, которому вы его назначаете:

Func<int> func = () => 5;

или передавая его делегату:

var func = (Func<int>)(() => 5);

Это необходимо, потому что вы можете представить, что ваш собственный делегат объявлен как

public delegate int MyDelegate();

Как бы компилятор узнал, должно ли ваше анонимное свойство типа быть напечатано как MyDelegate или же Func<int>?

Другие вопросы по тегам