MattDavey MattDavey - 1 month ago 4x
C# Question

Is there any reason we can't have some syntactic sugar around tuples?

What I would love to see in C# is better syntax around tuples eg.

var rgb = (1.0f, 1.0f, 1.0f);
// Inferred to be Tuple<float, float, float>
// Translated to var rgb = Tuple.Create(1.0f, 1.0f, 1.0f)


var x, y, z = rgb;

// Translated to:
// float x = rgb.Item1;
// float y = rgb.Item2;
// float z = rgb.Item3;

Is there anything in the C# language which prohibits this, or makes it too difficult/unrealistic to achieve? Perhaps there are other language features which would directly clash with this?

Note that I'm not asking if this is on Microsofts radar or even if it aligns with their vision for C#, just if there are any obvious blockers to it in theory.

Here are some examples from other CLI languages

// Nemerle - will use a tuple type from a language specific runtime library
def colour = (0.5f, 0.5f, 1.0f);
def (r, g, b) = colour;

// F# - Will use either a library type or `System.Tuple` depending on the framework version.
let colour = (0.5f, 0.5f, 1.0f)
let (r, g, b) = colour

// Boo - uses CLI array
def colour = (0.5, 0.5, 1.0)
def r, g, b = colour

// Cobra - uses CLI array
var colour = (0.5, 0.5, 1.0)
var r, g, b = colour

While using arrays might seem like a good compromise, it becomes limiting when mixing types eg.
let a, b = (1, "one")
F# or Nemerle will give us a
Tuple<int, string>
. In Boo or Cobra this would give us an

Language support for tuples is added in C# 7 -


The second syntax has been showed as non-doable by Tigran and Hilgarth.

Let's watch the first syntax:

var rgb = (1.0f, 1.0f, 1.0f);

What happen if you don't want to use the Tuple class, because instead you want to use the MyTuple class (that perhaps has the advantage of being IEnumerable<object>, something quite useful!)? Clearly that syntax won't help. You would have to put the MyTuple class somewhere...

MyTuple<float, float, float> rgb = (1.0f, 1.0f, 1.0f);


var rgb = new MyTuple<float, float, float>(1.0f, 1.0f, 1.0f);

now the advantage of this new shorthand syntax isn't present anymore, because somewhere you have to put the MyTuple<float, float, float>.

Note that there isn't any single collection initializer that simply "auto-discovers" everything.

var myVar = new List<int> { 1, 2, 3 };

Here the fact that we are speaking of a List<int> is quite clear :-)

Even the array initializer, that is a little "special", isn't implicit...

int[] myVar = { 1, 2, 3 };
var myVar = new[] { 1, 2, 3 };
var myVar = new int[] { 1, 2, 3 };

are all valid, but the fact that we are speaking of an array is always explicit (there is always a [])

var myVar = { 1, 2, 3 };

isn't valid :-) And the array has the "advantage" of being a primitive construct (arrays are supported directly by the IL language, while all the other collections are built on top of other .NET libraries and/or the arrays)