Home > Net >  why Positional Pattern doesn't work for records that have only one positional parameter?
why Positional Pattern doesn't work for records that have only one positional parameter?

Time:12-11

we know that we can use Positional Pattern below:

public record Person(string FirstName, string LastName);

Person p= new("John", "Citizen");

(var firstName, var lastName) = p;

Console.WriteLine($"first name is {firstName}, last name is {lastName}");

but if the record only has one positional parameter, then it doesn't work:

public record Person(string Name);

Person p= new("John Citizen");

(var name) = p;   // <------compile error

I remember record types need to have two or more positional parameters to have Deconstruct method generated by the compiler, but I was wrong, I checked the low-level code, singe positional parameter still have Deconstruct method generated by the compiler, then why (var name) = p doesn't work, and how can I make it work?

according to this post how does var pattern works with discard pattern?

I added the discard thing as:

(var name) _ = p;   // <------still compile error

but still it doesn't work

CodePudding user response:

You cannot do this. You cannot deconstruct one thing.

There was supposed to be an error that was implemented - CS8134 - that said something like:

Deconstructions are only allowed into two or more parts.

Here's the line of code in Roslyn that emits this. But somehow this line is not reached with either of these syntaxes:

(var x) = foo;
var (y) = foo;

Note that with the second line, I get

error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'Foo', with 2 out parameters and a void return type.

which is also a telling sign that deconstructing one thing is not possible, since it is looking for a 2-argument Deconstruct, even when I am trying to deconstruct one thing.

Interestingly, the Deconstruct method is still generated in the record if you look at the decompiled code - you just can't use it with the deconstruct syntax!

CodePudding user response:

Interestingly, deconstructing works during pattern matching as in this example:

public record Person(string Name);

Person p = new("John Citizen");

if (p is (var name) _)
{
    Console.WriteLine(name); // Output is John Citizen
}

CodePudding user response:

The problem with your code is that the compiler doesn't know which field of the Person record you want to deconstruct. Since the Person record only has one field, Name, you need to explicitly specify that you want to deconstruct that field. You can do this by either specifying the field name in the deconstruction pattern, like this:

public record Person(string Name);

Person p = new("John Citizen");

(var name) = p.Name;   // <------ no longer a compile error

Or you can use the Deconstruct method that is generated by the compiler for the Person record, like this:

public record Person(string Name);

Person p = new("John Citizen");

(var name) = p.Deconstruct();   // <------ no longer a compile error

In either case, the name variable will be assigned the value of the Name field of the Person record, which is "John Citizen" in this example.

  • Related