7

In C# 7, it's apparently not possible to destructure to a tuple with only one item.

ValueTuple<T1> exists, so it's not because of that.

And backwards compatibility means a Deconstruct method with one argument must also be legal:

public void Deconstruct(out int i)

So why couldn't you write:

var (num) = foo;

Is it simply that there's no sensible use case for this?

svick
  • 236,525
  • 50
  • 385
  • 514
Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
  • 4
    My guess is that it's to alleviate confusion between `var num = foo` and `var (num) = foo`, especially since it's rare for brackets to change the meaning of a program (excluding order of operations). Such a trade off may not be worth it, since as you point out, it's not *that* useful to destructure a single argument. – Rob Nov 20 '16 at 23:33
  • I'd bet on ambiguity with braced identifier expressions in some case. – Stilgar Nov 21 '16 at 00:09
  • 1
    In general, 1-tuples and 1-deconstructions raise all sorts of syntax ambiguity. Also, they don't seem very useful. The feature specs have this restriction built into the grammar at this point (see https://github.com/dotnet/roslyn/blob/master/docs/features/tuples.md#language-grammar-changes and https://github.com/dotnet/roslyn/blob/master/docs/features/deconstruction.md#grammar-changes ) – Julien Couvreur Jan 06 '17 at 01:36
  • We use optional refs in VB, and want to switch to C# and use tuples (since C# isn't going to add optional refs, which is another issue altogether). But we can't because tuples can't deconstruct just the first return value. Many other languages have 3 dots to skip the remaining values. – Brain2000 Nov 16 '21 at 18:31

2 Answers2

5

My guess: consider the following case:

int num;
(num) = foo;

If foo defines a deconstructor with out int and an implicit int cast operator, it will be ambiguous which should be invoked in this case

It is possible to have a compile error in this specific case while allowing the general case I guess, but since, as you mentioned, there is no use case and the syntax would be confusing, maybe it makes sense to not allow it at all

KMoussa
  • 1,568
  • 7
  • 11
1

I am working with Visual Studio 2017 RC. I have found that the Connect(); reference that you listed is incorrect. The example syntax that you listed does compile and works.

As a test I used the following code:

public class Foo
{
    public int Bar { get; set; }

    public void Deconstruct(out int bar)
    {
        bar = Bar;
    }
}

var foo = new Foo { Bar = 3 };
var (num) = foo; //num is an int with a value of 3
var obj = foo; //obj is a Foo object with the same reference as foo

In the above example the num variable is an int with a value of 3. The obj variable is a Foo object with the same reference as foo.

The following does not compile:

(int num) = foo; 
(var num) = foo;
//Both give error: The name `num` does not exist in the current context.
Matt Rowland
  • 4,575
  • 4
  • 25
  • 34