Returning Multiple Values From a Class Method (but not the full class)
Tags: dotnet
Published: 2022-10-23 16:48:24

_update: added benchmark_

It is not rare for you to want to return several values from a class method, but you don't need the full class. The options available in older versions of C# are less than optimal:

## Previous Available Solutions
- Out parameters: They don’t work with async methods.
- System.Tuple<...> Require an allocation of a tuple object.
- Custom-built transport type for every method: A lot of code overhead.
- Anonymous types returned through a dynamic return type: High performance-overhead and no static type checking.


## A Better Way (From C#7)
Let's say we are having a class Users, with a lot of fields, like Name, FirstName, Department, PhoneNumber, CurrentWorkingOnStatus, Email,...

Inside your app, on many occasions, you request to have the FirstName and the CurrentWorkingOnStatus.

### The User Class
```
public sealed class User
{
   public int id { get; set; }
   public string Name { get; set; }
   public string FirstName { get; set; }
   public string Email { get; set; }
   public string Phone { get; set; }
   public string Status { get; set; }

   /// Many Other fields
   public User() { }
   public User(int userid) { }

   public void Deconstruct(out string name, out string status) 
   { 
     name = FirstName; 
     status = Status; 
   }
 
   public static User GetCurrentUserStatus(int userid)
   {
      return new User() {FirstName= "Frederik"
            ,  Status = "Building CodeHelper NuGet Packages" };
   }
}
```
The `Deconstruct` method lets you unpackage all the items in a tuple in a single operation but can also be used with your class!

## The Code
The code will call GetCurrentUserStatus method, the return will be "deconstructed" into the 2 variables `_userName` and `_userStatus`.

```
var (_userName, _userStatus) = User.GetCurrentUserStatus(123);
Console.WriteLine($"{ _userName} is working on {_userStatus}");
```

In case you want to get the full class data back, with access to all properties ad methods, you still can do it
```
User _trending = User.GetCurrentUserStatus();
///-- You have access to a properties
```

### Multiple Deconstruct Methods?
Yes, it is possible to create multiple deconstruct methods, as long as they have a different number of out parameters
Add the following method to the user class
```
public void Deconstruct(out string name, out string email, out string phone) { 
            name = Name + " " + FirstName; 
            email = Email; 
            phone = Phone; 
        }
```
   

Add the following code to your app
```
var (_user, _email, _phone) = User.GetContactinfo(123);
Console.WriteLine($"{_user} can be contacted by phone  {_phone}");
```
   
## Solution without the Deconstruct Method
It is not always the best way to create many deconstruct methods, you can return multiple values  from your class methods directly
    
Add the following method the user class
```
public static (string name, string firstname) GetUserName()
{  
  return ("Van Lierde", "Frederk");  
}
```

Add the following code to your app
```
var (_name, _fname) = User.GetUserName();
Console.WriteLine($"Coder: {_name} {_fname}");
```
## Benchmark 

```
|           Method |     Mean |    Error |   StdDev |   Median | Allocated |
|----------------- |---------:|---------:|---------:|---------:|----------:|
| returnDestructor | 15.72 ns | 0.808 ns | 2.357 ns | 15.87 ns |      64 B |
|      returnClass | 18.15 ns | 1.288 ns | 3.757 ns | 16.52 ns |      64 B |
```
## Conclusion
These C# features make your code more readable, understandable and you use much less memory