Replies: 21 comments
-
The first two suggestions don't require changes at the language level (assuming an overload for each number of parameters is provided): public static class EnumerableExtensions
{
public static void Deconstruct<T>(this IEnumerable<T> values, out T item1, out T item2, out T item3)
{
var enumerator = values.GetEnumerator();
enumerator.MoveNext();
item1 = enumerator.Current;
enumerator.MoveNext();
item2 = enumerator.Current;
enumerator.MoveNext();
item3 = enumerator.Current;
}
public static void Deconstruct<T>(this IReadOnlyList<T> values, out T item1, out T item2, out T item3)
{
item1 = values[0];
item2 = values[1];
item3 = values[2];
}
} So maybe this should be an API proposal in CoreFX instead. |
Beta Was this translation helpful? Give feedback.
-
Needs an overload for every possible arity and can't be conditional, so an array of two elements could still be deconstructed into three variables. Conditional deconstruction solves that problem and requires language changes already so, in my opinion, it's worth evaluating whether or not a different syntax for collection deconstruction makes sense. |
Beta Was this translation helpful? Give feedback.
-
@HaloFour Conditional deconstruction? |
Beta Was this translation helpful? Give feedback.
-
While this is what a list pattern would do, you could already deconstruct a list with head/tail format, var (head, tail) = list;
var (first, (second, rest)) = list; You just need to populate the second |
Beta Was this translation helpful? Give feedback.
-
I don't see that as an issue. There's already an implementation of ValueTuple for each arity.
I don't understand, could you show an example? |
Beta Was this translation helpful? Give feedback.
-
Currently a public static class ArrayExtensions {
public static void Deconstruct<T>(this T[] input, out T item1, out T item2, out T item3) { ... }
} When used like this: var array = new int[] { 1, 2 };
var (a, b, c) = array; The implementation is required to either successfully deconstruct into three variables, assigning some arbirary sentinal default value for As a part of the larger pattern matching feature is conditional deconstruction where if (array is var (a, b, c)) {
// array has 3 elements
} |
Beta Was this translation helpful? Give feedback.
-
Thanks for the explanation, it's clear now. I personally think that throwing an exception would be ideal. If I used deconstruction on an array, it would mean that I have strong assumptions on the contents of the array, and I would expect that validation was properly done before reaching that point in the code. For instance, if that was parameters from a command: if (args.Length < 2)
{
// Incorrect parameters
}
var (path, mode) = args; // if the length is lower than 2, then an exception should be thrown, as something is definitely wrong with my validation code That said, I understand it's a matter of habits and taste. The conditional deconstruction is very interesting, as it allows to check the length implicitly. |
Beta Was this translation helpful? Give feedback.
-
As @alrz implies, there is already a well established pattern for handling deconstructing enumerations: var arr = new[]{1, 2, 3, 4};
var (a, (b, (c, d))) = arr; Regarding needing a specific data structure, the solution for me was to simply use a |
Beta Was this translation helpful? Give feedback.
-
I'm against this feature because it promotes a dangerous and bad design pattern- trying to store different pieces of data using number indexes in an array. This makes sense in a low level language but makes zero sense in C#. Use a real type (or a tuple!) to store your data instead. |
Beta Was this translation helpful? Give feedback.
-
using System;
static class ArrayDeconstruction
{
public static void Deconstruct<T>(this T[] x, out T head, out Span<T> tail)
{
head = x[0];
tail = new Span<T>(x).Slice(1);
}
public static void Deconstruct<T>(this Span<T> x, out T head, out Span<T> tail)
{
head = x[0];
tail = x.Slice(1);
}
}
class Program
{
static void Main(string[] args)
{
var x = new[] { 1, 2, 3, 4, 5 };
var (head, tail) = x;
Console.WriteLine(head);
Console.WriteLine(tail.Length);
}
} |
Beta Was this translation helpful? Give feedback.
-
This claim makes no sense to me. You already can "store different pieces of data using number indexes in an array"; use an object array. I really can't think of a use case where being able to deconstruct that array to a tuple would then promote that behaviour as it would require the writing of custom deconstructors to handle those mixed types. |
Beta Was this translation helpful? Give feedback.
-
When you think of this as a pattern (that can fail) you can do the matching in a self-contained way. For example, imagine you want to write an analyzer to convert as/null-check to use pattern matching, for that you should find a subsequent variable declaration and if statement. var statements = block.Statements;
if (statements is { LocalDeclarationStatement localDecalration, IfStatement ifStatement, ___ }) (the last pattern is a sequence discard: #305) We already do this kind of things manually but with recursive and extension patterns it becomes a lot more declarative. The final pattern-matching proposal is not out yet but I think we can extend deconstruction assignment to support irrefutable patterns: dotnet/roslyn#16183. |
Beta Was this translation helpful? Give feedback.
-
It seems related with the spread/rest syntax now Javascript have. |
Beta Was this translation helpful? Give feedback.
-
Tagging @agocke who is writing a proposal for a new kind of pattern that would address this. If I recall, he was thinking something like |
Beta Was this translation helpful? Give feedback.
-
Awesome to hear! Can you mix and match? I assume that those would be recursive patterns? 🍝 if (collection is [ var first, var second, var third : _ ]) {
Console.WriteLine($"The first three elements are {first}, {second} and {third}.");
} if (collection is [ var first : _ : var last ]) {
Console.WriteLine($"The first element is {first} and the last element is {last}.");
} |
Beta Was this translation helpful? Give feedback.
-
Also curious as to what type "rest" would be? |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
@HaloFour Yes, those would be recursive. |
Beta Was this translation helpful? Give feedback.
-
Related discussion: #1039. |
Beta Was this translation helpful? Give feedback.
-
I'd like to have |
Beta Was this translation helpful? Give feedback.
-
See the championed proposal: #3435 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
@Velocirobtor commented on Sat Oct 01 2016
Since Deconstruction is probably going to make it into C#, I think it would be awesome to allow Deconstruction of Collections/Enumerables:
Python for example already has a similar feature and I think it's quite useful.
As for a possible Implementation:
Since Deconstruction will probably be via a Deconstruction Method with out parameters, allowing out params could do the trick:
This way all Enumerables could be deconstructed.
@svick commented on Sat Oct 01 2016
Related: dotnet/roslyn#10631
@jcouv commented on Fri Sep 01 2017
Discussion of language features are being moved over to csharplang. I'll move this issue over.
Beta Was this translation helpful? Give feedback.
All reactions