6

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)

And

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.

Edit 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 object[].

Edit2 Language support for tuples is added in C# 7 - https://www.kenneth-truyers.net/2016/01/20/new-features-in-c-sharp-7/

MattDavey
  • 8,897
  • 3
  • 31
  • 54
  • 1
    It seems like this would be "syntactic-sugar" for a very limited scope; I also feel like it is obscure. Is it really so hard to write `var rgb = Tuple.Create(1.0f, 1.0f, 1.0f);`? Your intent should remain clear in your code. – crush Sep 10 '13 at 12:37
  • 4
    Tuples don't have descriptive names for its members. Item1, Item2, Item3... Actually I still wonder why tuples were added. Spend a minute - write a `Color` class, and remove that ugly `Item1`, `Item2`, `Item3`, `Tuple` – Sergey Berezovskiy Sep 10 '13 at 12:41
  • 2
    This would make the library and the language more fused together than they are. What if you don't want to use the `Tuple` class but you want to use `MyTuple`? As it's now only arrays have a special initializer `int[] x = { 1, 2 }`, but arrays are a very primitive type, not buildable with standard .NET . – xanatos Sep 10 '13 at 12:42
  • 3
    @lazyberezovsky Even a guy with lazy in his name would rather write a class than deal with `Tuple`s! I'm with you! – weston Sep 10 '13 at 12:49
  • 1
    @lazyberezovsky - I was curious too ([eric lippert answer](http://stackoverflow.com/a/3089883/1324033)).. OP I really don't think their correct usage warrants a short hand approach – Sayse Sep 10 '13 at 12:50
  • @xanatos that's a good reason, could you put that comment into an answer so I can upvote it? – MattDavey Sep 10 '13 at 13:04
  • @xanatos: That's incorrect. The *collection initializer* can be used for every class with an `Add` method... Even for dictionaries. – Daniel Hilgarth Sep 10 '13 at 13:11
  • 1
    @DanielHilgarth But you have to do a new `List { }`. They can't implicitly discover the type from the lvalue, like `int[] x = { }`. With collection initializer it would be `new Tuple { 1, 2 }`... I don't see a big advantage to `new Tuple(1, 2)` – xanatos Sep 10 '13 at 13:24
  • @xanatos: Now I see where you are headed. Yeah, that's right, that really only works for arrays. – Daniel Hilgarth Sep 10 '13 at 13:27

3 Answers3

4

The second one is not possible, because it already means something else:

float x, y, z = 0.1f;

This declares three variables x, y and z with z being initialized to 0.1. The difference to the syntax proposed in your question is subtle at best.

Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
4

It's clearly a design issue as in your case you assign value only to last variable, where other two assume default values of specified type.

var x, y, z = rgb;

So whatever rgb is, only z becomes assigned to it. If you change this behavior, it would be absolutely unclear what is going on that line:

  • assignment to all variable
  • assignment only to last one

If you will not make clear decision here, it would lead to different behavior based on the type on the right side of assignment operator: in one case it would be declaration and assignment do default value, in another case declaration and assignment to specific value.

Tigran
  • 61,654
  • 8
  • 86
  • 123
1

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);

or

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)

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • 1
    +1 this is an interesting point, especially about the special status of arrays in IL. I wonder why this isn't an issue in other CLI languages which do support this kind of tuple syntax (Boo, F#, Nemerle, Cobra). In Boo, `def rgb = (1f, 1f, 1f)` would give us an array of 3 floats. F# and Nemerle would give us built in tuple types - tieing us into a language specific runtime library. – MattDavey Sep 11 '13 at 09:30
  • Correction: F# may use the `System.Tuple` type, depending on the target framework version. – MattDavey Sep 11 '13 at 09:38
  • @MattDavey `var myVar = { 1, 2, 3 };` would be probably easy to make it in C#. For some reasons they decided to not do it. For the tuples, other languages have primitive tuples, and clearly .NET implementations of those languages must have them. It isn't "impossible", simply you have to decide that your tuple (your language tuple implementation) is the only "true" tuple implementation. – xanatos Sep 11 '13 at 09:47
  • 1
    ahh, and a programming language which strives to be general purpose would certainly not want to make that kind of definitive decision, or impose that decision onto its users. I think that may be the answer to my question. – MattDavey Sep 11 '13 at 09:51
  • @MattDavey Yes. In my response I added that someone could want a `Tuple` with `IEnumerable`, and I was nearly joking, but a `MutableTuple<>` would surely be an interesting option. – xanatos Sep 11 '13 at 09:54