C# Functions - Returning multiple values with Tuple Literals

4/14/2021

Although somewhat rare, I've had my times of needing to return multiple values from a function. The options at the time were:

  • Using System.Tuple< ... > return types . They do work. But require an allocation, and the caller has to access via the uninformative Item1, Item2.
  • Using out parameters. They do work, but not ideal (and no async support).
  • Create a custom container class. Been there, done that. Don't like it.

Tuple Types and Tuple Literals

C# 7 has a better solution via Tuples. Here's a simple example for getting a US State name and its abbreviation in one call:

public (string, string) LookupUsState(long stateId) // tuple return type
{
    ... // get from data storage
    return (StateName, StateAbbv); // tuple literal
}

// Caller example:
void foo()
{
  (name, abbv) LookupState(1);
  Console.WriteLine($"State: {name} ({abbv})");
}

As you can see, these are rather simple to use.

My real-world example, including Generics

At work, I needed to write a function which calls an InRule engine and return a custom object with the results. The code was simple:

public O GetRuleResponseAndResult<I, O>(I input)
{
    string entityJson = Newtonsoft.Json.JsonConvert.SerializeObject(input);
    var response = ExecuteRuleSetJson(ruleApp, ruleset, entity, entityJson, returnEntity);
    return Newtonsoft.Json.JsonConvert.DeserializeObject<O>(response.EntityJson);
}

Later we realized that the response object on line 5 has some information we needed, including error and validation information. I really didn't want to use any of the three options above. C#7 now made it simple:

public (RuleExecutionResponse, O) GetRuleResponseAndResult<I, O>(I input)
{
    string entityJson = Newtonsoft.Json.JsonConvert.SerializeObject(input);
    var response = ExecuteRuleSetJson(ruleApp, ruleset, entity, entityJson, returnEntity);
    O result = Newtonsoft.Json.JsonConvert.DeserializeObject<O>(response.EntityJson);
    return (response, result); // returning both objects
}

// Calling code:
var (response, output) = GetRuleResponseAndResult<EnDRuleOutput, EnDInput>(input);
if (response.Error == null)
{
   // Do something with output
}

Rather clean. Happy coding...


Please register or login to add a comment.

Comments (displaying 1 - 1):
No comments yet! Be the first...


  • C#/.NET
  • T-SQL
  • HTML/CSS
  • JavaScript/jQuery
  • .NET 8
  • ASP.NET/MVC
  • Xamarin/MAUI
  • WPF
  • Windows 11
  • SQL Server 20xx
  • Android
  • XBox
  • Arduino
  • Skiing
  • Rock Climbing
  • White water kayaking
  • Road Biking