Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does C# 7 have array/enumerable destructuring?

In JavaScript ES6, you are able to destructure arrays like this:

const [a,b,...rest] = someArray; 

where a is the first element in the array, b is the second, and rest is an array with the remaining elements.

I know in C#7 that you can destructure tuples during assignment, but could not find anything related to destructuring arrays/enumerables like this:

var (a,b) = someTuple; 

I have an IEnumerable where I need the first and second elements as variables, and I need the rest of the elements as another IEnumerable. I have a solution, but feel that destructuring will look cleaner.

like image 757
kmc059000 Avatar asked Dec 14 '17 14:12

kmc059000


People also ask

What is the do in C?

The do-while statement lets you repeat a statement or compound statement until a specified expression becomes false.

What does |= mean in C?

The ' |= ' symbol is the bitwise OR assignment operator.


2 Answers

It turns out not only tuples can be deconstructed but any type which has Deconstruct static (or extension) method with matching signature. Doing deconstruction correctly for IEnumerable is not trivial (see library suggested by David Arno in this answer), so let's see how it works with simple IList instead (implementation is irrelevant, this one is for example and of course can be better/different):

public static class Extensions {     public static void Deconstruct<T>(this IList<T> list, out T first, out IList<T> rest) {         first = list.Count > 0 ? list[0] : default(T); // or throw         rest = list.Skip(1).ToList();     }      public static void Deconstruct<T>(this IList<T> list, out T first, out T second, out IList<T> rest) {         first = list.Count > 0 ? list[0] : default(T); // or throw         second = list.Count > 1 ? list[1] : default(T); // or throw         rest = list.Skip(2).ToList();     } } 

Then (after adding relevant using statements if necessary) you can use exactly the syntax you want:

var list = new [] {1,2,3,4}; var (a,rest) = list; var (b,c,rest2) = list; 

Or you can chain deconstruction like this (because last returned value can itself be deconstructed):

 var (a, (b, (c, rest))) = list; 

With last version, you can deconstruct to any number of items using single Deconstruct method (that one which returns first item and the rest).

For real usage for IEnumerables, I'd suggest to not reimplement the wheel and use David Arno's library mentioned in this answer.

like image 62
Evk Avatar answered Sep 28 '22 20:09

Evk


What you are describing is generally known in functional languages as "cons", which often takes the form:

let head :: tail = someCollection 

I did propose this be added to C#, but it didn't receive very favourable feedback. So I wrote my own, which you can use via the Succinc<T> nuget package.

It uses deconstruction to achieve that splitting of the head and tail of any IEnumerable<T>. Deconstructs can be nested, so you can use it to extract multiple elements in one go:

var (a, (b, rest)) = someArray; 

This potentially could provide the functionality you are after.

like image 38
David Arno Avatar answered Sep 28 '22 20:09

David Arno