KeyValuePair naming by ValueTuple in C# 7
Asked Answered
D

1

13

Can the new feature in C# 7.0 (in VS 2017) to give tuple fields names be translated to KeyValuePairs?

Lets assume I have this:

class Entry
{
  public string SomeProperty { get; set; }
}

var allEntries = new Dictionary<int, List<Entry>>();
// adding some keys with some lists of Entry

It would be nice to do something like:

foreach ((int collectionId, List<Entry> entries) in allEntries)

I have already added System.ValueTuple to the project.

Being able to write it like that would be much better than this traditional style:

foreach (var kvp in allEntries)
{
  int collectionId = kvp.Key;
  List<Entry> entries = kvp.Value;
}
Demolish answered 7/4, 2017 at 15:51 Comment(3)
Please provide a minimal reproducible example. We don't know what allEntries is, which makes it really hard to try to help...Norseman
@JonSkeet I added more data about what kind of Dictionary this could be although the question is generic, could be a Dictionary<int, string> as well.Demolish
Just the fact that it's a Dictionary<,> is a good start - you hadn't mentioned that before. I think it would be simpler if you rewrote the question with a minimal reproducible example using Dictionary<int, string> though. I'll have a look in a bit...Norseman
F
20

Deconstruction requires a Deconstruct method defined either on the type itself, or as an extension method. KeyValuePaire<K,V> itself doesn't have a Deconstruct method, so you need to define an extension method:

static class MyExtensions
{
    public static void Deconstruct<K,V>(this KeyValuePair<K,V> kvp, out K key, out V value)
    {
      key=kvp.Key;
      value=kvp.Value;
    }
}

This allows you to write:

var allEntries = new Dictionary<int, List<Entry>>();
foreach(var (key, entries) in allEntries)
{
    ...
}

For example:

var allEntries = new Dictionary<int, List<Entry>>{
    [5]=new List<Entry>{
                        new Entry{SomeProperty="sdf"},
                        new Entry{SomeProperty="sdasdf"}
                        },
    [11]=new List<Entry>{
                        new Entry{SomeProperty="sdfasd"},
                        new Entry{SomeProperty="sdasdfasdf"}
                        },    };
foreach(var (key, entries) in allEntries)
{
    Console.WriteLine(key);
    foreach(var entry in entries)
    {
        Console.WriteLine($"\t{entry.SomeProperty}");
    }
}
Frenchman answered 7/4, 2017 at 16:11 Comment(5)
Note that KeyValuePair will have Deconstruct in .Net Core 2.0 (and likely also some future versions of .Net Standard and .Net Framework).Solace
Are you sure that works? Isn't Deconstruct supposed to allow to deconstruct a type the way you deconstruct a tuple. Not into a tuple.Brunet
The code compiles and runs. Besides, this snippet doesn't create a tuple, it deconstructs a KVP into two variables. That's not different than the Point example in What's new in C# 7.Frenchman
I think it is different as the Point example calls a method where the out-parameters are declared in the parameter call but here the return value is split. There are similarities, though. But this writing requires an appropiate Deconstruct. In this end this is just syntax sugar but I like it.Demolish
@Demolish It's exactly the same code (var myX, var myY) = GetPoint(); class Point { /* ... */ public void Deconstruct(out int x, out int y) { x = X; y = Y; } } except the here an extension method is used instead of declaration in the class.Lacefield

© 2022 - 2024 — McMap. All rights reserved.