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);
}
Лямбда-выражения не имеют типа. Вот почему вы должны добавить компилятору некоторую информацию, чтобы определить его тип (давая им некоторый контекст).
Обратите внимание, что лямбда-выражения сами по себе не имеют типа, потому что в общей системе типов нет внутреннего понятия "лямбда-выражения". Однако иногда удобно неформально говорить о "типе" лямбда-выражения. В этих случаях тип относится к типу делегата или типу выражения, в которые преобразуется лямбда-выражение.
Вы можете сделать это по типу переменной / параметра / свойства / поля, которому вы его назначаете:
Func<int> func = () => 5;
или передавая его делегату:
var func = (Func<int>)(() => 5);
Это необходимо, потому что вы можете представить, что ваш собственный делегат объявлен как
public delegate int MyDelegate();
Как бы компилятор узнал, должно ли ваше анонимное свойство типа быть напечатано как MyDelegate
или же Func<int>
?