Деконструкция в foreach над словарем

Возможно ли в С# 7 использовать деконструкцию в foreach-loop над словарем? Что-то вроде этого:

var dic = new Dictionary<string, int>{ ["Bob"] = 32, ["Alice"] = 17 };
foreach (var (name, age) in dic)
{
    Console.WriteLine($"{name} is {age} years old.");
}

Он не работает с Visual Studio 2017 RC4 и .NET Framework 4.6.2:

ошибка CS1061: "KeyValuePair" не содержит определения для "Deconstruct", и не может быть найден метод расширения "Deconstruct", принимающий первый аргумент типа "KeyValuePair" (вам не хватает директивы using или ссылки на сборку?)

Ответ 1

Сначала вам нужно добавить метод расширения для KeyValuePair:

public static void Deconstruct<T1, T2>(this KeyValuePair<T1, T2> tuple, out T1 key, out T2 value)
{
    key = tuple.Key;
    value = tuple.Value;
}

Затем вы получите другую ошибку:

ошибка CS8179: предопределенный тип 'System.ValueTuple`2' не определен или не импортирован

В соответствии с этим ответом вам необходимо установить пакет NuGet System.ValueTuple.

Затем он должен скомпилироваться. Однако Visual Studio 2017 RC4 скажет, что он не может разрешить имена символов name и age. Они должны надеяться исправить это в будущем обновлении.

Ответ 2

Если вам не нравится писать метод Deconstruct, особенно если он вам нужен только в одном месте, здесь, как сделать это как одну строку с LINQ:

Используя ваш оригинальный словарь:

var dic = new Dictionary<string, int>{ ["Bob"] = 32, ["Alice"] = 17 };

Вы можете сделать это так:

foreach (var (name, age) in dic.Select(x => (x.Key, x.Value)))
{
    Console.WriteLine($"{name} is {age} years old.");
}

Ответ 3

Deconstruct KeyValuePair<TKey,TValue> реализована в .NET Core 2.0, но, к сожалению, не в .NET Framework (предварительный просмотр до 4.8).