Return multiple values to a method caller
Asked Answered
M

28

665

I read the C++ version of this question but didn't really understand it.

Can someone please explain clearly if it can be done in C#, and how?

Michale answered 14/4, 2009 at 15:11 Comment(1)
based on answer of mentioned question, in C/C++ & before variable name mean pass by reference, use reference parameters you can pass variable to function and change it's value inside function, in C# you can do it with ref / out parametersWoodsman
T
798

In C# 7 and above, see this answer.

In previous versions, you can use .NET 4.0+'s Tuple:

For Example:

public Tuple<int, int> GetMultipleValue()
{
     return Tuple.Create(1,2);
}

Tuples with two values have Item1 and Item2 as properties.

Typesetting answered 23/4, 2012 at 10:24 Comment(5)
It would be very very nice if instead of Item1, Item2 and so on one could use named output values. C# 7 possibly is going to provide that.Mutineer
@Sнаđошƒаӽ is absolutely right this is expected to be supported in the upcoming C# 7.0 using a syntax like: public (int sum, int count) GetMultipleValues() { return (1, 2); } This example was taken from our Documentation topic example on this.Bemean
How do I catch the returned tuple and access them on the caller side?Cogwheel
@Cogwheel See example in the docs. For this example we would do something like: (int num1, int num2) = GetMultipleValue();Sigridsigsmond
Although possible to use Tuples for that purpose, I'd advise against that. Consider creating a class so you can give a name to what you're returning, otherwise other devs will have to F12 into the method to see what's being returned there, making maintenance harder than it should be.Grimace
S
841

Now that C# 7 has been released, you can use the new included Tuples syntax

(string, string, string) LookupName(long id) // tuple return type
{
    ... // retrieve first, middle and last from data storage
    return (first, middle, last); // tuple literal
}

which could then be used like this:

var names = LookupName(id);
WriteLine($"found {names.Item1} {names.Item3}.");

You can also provide names to your elements (so they are not "Item1", "Item2" etc). You can do it by adding a name to the signature or the return methods:

(string first, string middle, string last) LookupName(long id) // tuple elements have names

or

return (first: first, middle: middle, last: last); // named tuple elements in a literal

They can also be deconstructed, which is a pretty nice new feature:

(string first, string middle, string last) = LookupName(id1); // deconstructing declaration

Check out this link to see more examples on what can be done :)

Shull answered 5/4, 2016 at 20:19 Comment(4)
If you're targeting anything earlier than .NET Framework 4.7 or .NET Core 2.0, you'll need to install a NuGet package.Dormancy
To get the return you can do: "var result = LookupName(5); Console.WriteLine(result.middle)".Adolescent
(string,string, string) is much simplier than defining the function return type as Tuple<string,string,string> and returning a create Tuple<value1, value2, value3>Rabideau
Can you use LookupName(id1) product in calling DoSomethingWtthName(string first, string last) method directly somehow? DoSomethingWithName(<take first and last from..>LookupName(id))Bairn
T
798

In C# 7 and above, see this answer.

In previous versions, you can use .NET 4.0+'s Tuple:

For Example:

public Tuple<int, int> GetMultipleValue()
{
     return Tuple.Create(1,2);
}

Tuples with two values have Item1 and Item2 as properties.

Typesetting answered 23/4, 2012 at 10:24 Comment(5)
It would be very very nice if instead of Item1, Item2 and so on one could use named output values. C# 7 possibly is going to provide that.Mutineer
@Sнаđошƒаӽ is absolutely right this is expected to be supported in the upcoming C# 7.0 using a syntax like: public (int sum, int count) GetMultipleValues() { return (1, 2); } This example was taken from our Documentation topic example on this.Bemean
How do I catch the returned tuple and access them on the caller side?Cogwheel
@Cogwheel See example in the docs. For this example we would do something like: (int num1, int num2) = GetMultipleValue();Sigridsigsmond
Although possible to use Tuples for that purpose, I'd advise against that. Consider creating a class so you can give a name to what you're returning, otherwise other devs will have to F12 into the method to see what's being returned there, making maintenance harder than it should be.Grimace
S
285

You can use three different ways

1. ref / out parameters

using ref:

static void Main(string[] args)
{
    int a = 10;
    int b = 20;
    int add = 0;
    int multiply = 0;
    Add_Multiply(a, b, ref add, ref multiply);
    Console.WriteLine(add);
    Console.WriteLine(multiply);
}

private static void Add_Multiply(int a, int b, ref int add, ref int multiply)
{
    add = a + b;
    multiply = a * b;
}

using out:

static void Main(string[] args)
{
    int a = 10;
    int b = 20;
    int add;
    int multiply;
    Add_Multiply(a, b, out add, out multiply);
    Console.WriteLine(add);
    Console.WriteLine(multiply);
}

private static void Add_Multiply(int a, int b, out int add, out int multiply)
{
    add = a + b;
    multiply = a * b;
}

2. struct / class

using struct:

struct Result
{
    public int add;
    public int multiply;
}
static void Main(string[] args)
{
    int a = 10;
    int b = 20;
    var result = Add_Multiply(a, b);
    Console.WriteLine(result.add);
    Console.WriteLine(result.multiply);
}

private static Result Add_Multiply(int a, int b)
{
    var result = new Result
    {
        add = a * b,
        multiply = a + b
    };
    return result;
}

using class:

class Result
{
    public int add;
    public int multiply;
}
static void Main(string[] args)
{
    int a = 10;
    int b = 20;
    var result = Add_Multiply(a, b);
    Console.WriteLine(result.add);
    Console.WriteLine(result.multiply);
}

private static Result Add_Multiply(int a, int b)
{
    var result = new Result
    {
        add = a * b,
        multiply = a + b
    };
    return result;
}

3. Tuple

Tuple class

static void Main(string[] args)
{
    int a = 10;
    int b = 20;
    var result = Add_Multiply(a, b);
    Console.WriteLine(result.Item1);
    Console.WriteLine(result.Item2);
}

private static Tuple<int, int> Add_Multiply(int a, int b)
{
    var tuple = new Tuple<int, int>(a + b, a * b);
    return tuple;
}

C# 7 Tuples

static void Main(string[] args)
{
    int a = 10;
    int b = 20;
    (int a_plus_b, int a_mult_b) = Add_Multiply(a, b);
    Console.WriteLine(a_plus_b);
    Console.WriteLine(a_mult_b);
}

private static (int a_plus_b, int a_mult_b) Add_Multiply(int a, int b)
{
    return(a + b, a * b);
}
Sebastien answered 3/6, 2015 at 23:4 Comment(4)
For your info, a small (irrelevant) typo: In the struct/class solutions you mixed up adding/multiplying.Biernat
I suggest putting C# 7 Tuples as the top option. It's by far the best one, IMO.Taster
The ref / out parameters should be avoided for this purpose as they can clutter up the code. The Tuple is the best optionBurgwell
@Burgwell isn't out the closest thing C# has to native multiple return? The tuple probably is the best option for readability. Personally, I'm not keen on having anonymous types or property names like Item1 - although I guess destructuring does mitigate that. The last example, in terms of source code, definitely looks the most like multiple return in languages with that as a native feature. It's too bad there are so many options we need to choose from.Pietje
C
75

You cannot do this in C#. What you can do is have a out parameter or return your own class (or struct if you want it to be immutable).

Using out parameter
public int GetDay(DateTime date, out string name)
{
  // ...
}
Using custom class (or struct)
public DayOfWeek GetDay(DateTime date)
{
  // ...
}

public class DayOfWeek
{
  public int Day { get; set; }
  public string Name { get; set; }
}
Compartmentalize answered 14/4, 2009 at 15:16 Comment(5)
An alternative in this case is to use a struct instead of a class for the return type. If the return value is stateless and transient, struct is a better choice.Joashus
This is not possible with async methods. Tuple is the way to go. (I use out parameters in synchronous operations though; they are indeed useful in those cases.)Poult
This is now possible in C# 7: (int, int) Method() { return (1, 2); }Rager
Answer needs to be updated, it has become flat out wrong with recent versions of c#. will change downvote to upvote if updated.Bony
Working on a legacy code base, returning a custom class was a solid approach for me.Greywacke
B
67

In C#7 There is a new Tuple syntax:

static (string foo, int bar) GetTuple()
{
    return ("hello", 5);
}

You can return this as a record:

var result = GetTuple();
var foo = result.foo
// foo == "hello"

You can also use the new deconstructor syntax:

(string foo) = GetTuple();
// foo == "hello"

Be careful with serialisation however, all this is syntactic sugar - in the actual compiled code this will be a Tuple<string, int> (as per the accepted answer) with Item1 and Item2 instead of foo and bar. That means that serialisation (or deserialisation) will use those property names instead.

So, for serialisation declare a record class and return that instead.

Also new in C#7 is an improved syntax for out parameters. You can now declare the out inline, which is better suited in some contexts:

if(int.TryParse("123", out int result)) {
    // Do something with result
}

However, mostly you'll use this in .NET's own libraries, rather than in you own functions.

Beneficence answered 9/3, 2017 at 11:43 Comment(2)
Please note that, depending on what .Net version you're targeting, you may need to install Nuget package System.ValueTuple.Suicide
i was about to answer as above ;-)Rabbi
R
42

If you mean returning multiple values, you can either return a class/struct containing the values you want to return, or use the "out" keyword on your parameters, like so:

public void Foo(int input, out int output1, out string output2, out string errors) {
    // set out parameters inside function
}
Rothberg answered 14/4, 2009 at 15:15 Comment(2)
I don't think it good to use "out" or "ref"——because it can be totally substituted by a returned-value of your own class type. you see, if using "ref", how to assign to such parameters? (It just depends on how to code inside). If in the body of the function, the author has "newed" an instance to the parameter with "ref", this means you can just pass a "nullable" value there. Otherwises not. So that's a little ambigent. And we have better ways (1. Returning your owned class, 2. Turple).Diatessaron
This is the only answer that will work with ref struct. Like for example Span<T>. You cannot return Span's inside a tuple.Grati
G
39

There is many way; but if you don't want to create a new Object or structure or something like this you can do like below after C# 7.0 :

 (string firstName, string lastName) GetName(string myParameter)
    {
        var firstName = myParameter;
        var lastName = myParameter + " something";
        return (firstName, lastName);
    }

    void DoSomethingWithNames()
    {
        var (firstName, lastName) = GetName("myname");

    }
Gaynell answered 5/9, 2019 at 14:42 Comment(1)
Pay Attention to the var that is used before the tuple!Volcanism
K
34

Previous poster is right. You cannot return multiple values from a C# method. However, you do have a couple of options:

  • Return a structure that contains multiple members
  • Return an instance of a class
  • Use output parameters (using the out or ref keywords)
  • Use a dictionary or key-value pair as output

The pros and cons here are often hard to figure out. If you return a structure, make sure it's small because structs are value type and passed on the stack. If you return an instance of a class, there are some design patterns here that you might want to use to avoid causing problems - members of classes can be modified because C# passes objects by reference (you don't have ByVal like you did in VB).

Finally you can use output parameters but I would limit the use of this to scenarios when you only have a couple (like 3 or less) of parameters - otherwise things get ugly and hard to maintain. Also, the use of output parameters can be an inhibitor to agility because your method signature will have to change every time you need to add something to the return value whereas returning a struct or class instance you can add members without modifying the method signature.

From an architectural standpoint I would recommend against using key-value pairs or dictionaries. I find this style of coding requires "secret knowledge" in code that consumes the method. It must know ahead of time what the keys are going to be and what the values mean and if the developer working on the internal implementation changes the way the dictionary or KVP is created, it could easily create a failure cascade throughout the entire application.

Kaoliang answered 14/4, 2009 at 15:18 Comment(1)
And you can also throw an Exception if the second value you want to return is disjunctive from the first one: like when you want to return either a kind of successful value, or a kind of unsuccessful value.Exceptionable
M
24

You either return a class instance or use out parameters. Here's an example of out parameters:

void mymethod(out int param1, out int param2)
{
    param1 = 10;
    param2 = 20;
}

Call it like this:

int i, j;
mymethod(out i, out j);
// i will be 20 and j will be 10
Madrigal answered 14/4, 2009 at 15:16 Comment(3)
Remember, though that just because you can, doesn't mean you should do this. This is widely accepted as a bad practice in .Net in most cases.Joashus
Can you elaborate why is this a bad practise?Cystectomy
It's a bad practice in C/C++. The problem is "programming by side effect": int GetLength(char *s) { int n = 0; while (s[n] != '\0') n++; s[1] = 'X'; return (n); } int main() { char greeting[5] = { 'H', 'e', 'l', 'p', '\0' }; int len = GetLength(greeting); cout << len << ": " << greeting; // Output: 5: HXlp } In C# you would have to write: int len = GetLength(ref greeting) Which would signal a big warning flag of "Hey, greeting is not going to be the same after you call this" and greatly reduce bugs.Augite
W
18

Some answers suggest using out parameters but I recommend not using this due to they don’t work with async methods. See this for more information.

Other answers stated using Tuple, which I would recommend too but using the new feature introduced in C# 7.0.

(string, string, string) LookupName(long id) // tuple return type
{
    ... // retrieve first, middle and last from data storage
    return (first, middle, last); // tuple literal
}

var names = LookupName(id);
WriteLine($"found {names.Item1} {names.Item3}.");

Further information can be found here.

Waly answered 27/8, 2016 at 16:24 Comment(0)
A
15
<--Return more statements like this you can --> 

public (int,string,etc) Sample( int a, int b)  
{
    //your code;
    return (a,b);  
}

You can receive code like

(c,d,etc) = Sample( 1,2);

I hope it works.

Ardoin answered 18/1, 2019 at 4:30 Comment(1)
This answer is perfect, does exactly what's needed. Really helpful, thanks!Thermosiphon
C
12

No, you can't return multiple values from a function in C# (for versions lower than C# 7), at least not in the way you can do it in Python.

However, there are a couple alternatives:

You can return an array of type object with the multiple values you want in it.

private object[] DoSomething()
{
    return new [] { 'value1', 'value2', 3 };
}

You can use out parameters.

private string DoSomething(out string outparam1, out int outparam2)
{
    outparam1 = 'value2';
    outparam2 = 3;
    return 'value1';
}
Caracole answered 14/4, 2009 at 15:18 Comment(0)
I
11

There are several ways to do this. You can use ref parameters:

int Foo(ref Bar bar) { }

This passes a reference to the function thereby allowing the function to modify the object in the calling code's stack. While this is not technically a "returned" value it is a way to have a function do something similar. In the code above the function would return an int and (potentially) modify bar.

Another similar approach is to use an out parameter. An out parameter is identical to a ref parameter with an additional, compiler enforced rule. This rule is that if you pass an out parameter into a function, that function is required to set its value prior to returning. Besides that rule, an out parameter works just like a ref parameter.

The final approach (and the best in most cases) is to create a type that encapsulates both values and allow the function to return that:

class FooBar 
{
    public int i { get; set; }
    public Bar b { get; set; }
}

FooBar Foo(Bar bar) { }

This final approach is simpler and easier to read and understand.

Inclination answered 14/4, 2009 at 15:19 Comment(0)
M
11

you can try this "KeyValuePair"

private KeyValuePair<int, int> GetNumbers()
{
  return new KeyValuePair<int, int>(1, 2);
}


var numbers = GetNumbers();

Console.WriteLine("Output : {0}, {1}",numbers.Key, numbers.Value);

Output :

Output : 1, 2

Masturbate answered 6/3, 2012 at 10:53 Comment(0)
P
10

In C# 4, you will be able to use built-in support for tuples to handle this easily.

In the meantime, there are two options.

First, you can use ref or out parameters to assign values to your parameters, which get passed back to the calling routine.

This looks like:

void myFunction(ref int setMe, out int youMustSetMe);

Second, you can wrap up your return values into a structure or class, and pass them back as members of that structure. KeyValuePair works well for 2 - for more than 2 you would need a custom class or struct.

Protuberant answered 14/4, 2009 at 15:17 Comment(0)
G
10

When your method is async and you want to return multiple properties. You must do like this:

public async Task<(int, int)> GetMultipleValues(){
   return (1,2);
}
Gravure answered 8/3, 2022 at 15:30 Comment(2)
And how would this look on the caller?Reims
@ComeIn, var (num1, num2) = await GetMultipleValues();Gravure
R
5

Classes, Structures, Collections and Arrays can contain multiple values. Output and reference parameters can also be set in a function. Return multiple values is possible in dynamic and functional languages by means of tuples, but not in C#.

Reynolds answered 14/4, 2009 at 15:16 Comment(0)
H
4

Mainly two methods are there. 1. Use out/ref parameters 2. Return an Array of objects

Hush answered 14/4, 2009 at 15:51 Comment(1)
There's also tuples, and multiple return values as a syntactic sugar for tuples.Quintero
R
4

Here are basic Two methods:

1) Use of 'out' as parameter You can use 'out' for both 4.0 and minor versions too.

Example of 'out':

using System;

namespace out_parameter
{
  class Program
   {
     //Accept two input parameter and returns two out value
     public static void rect(int len, int width, out int area, out int perimeter)
      {
        area = len * width;
        perimeter = 2 * (len + width);
      }
     static void Main(string[] args)
      {
        int area, perimeter;
        // passing two parameter and getting two returning value
        Program.rect(5, 4, out area, out perimeter);
        Console.WriteLine("Area of Rectangle is {0}\t",area);
        Console.WriteLine("Perimeter of Rectangle is {0}\t", perimeter);
        Console.ReadLine();
      }
   }
}

Output:

Area of Rectangle is 20

Perimeter of Rectangle is 18

*Note:*The out-keyword describes parameters whose actual variable locations are copied onto the stack of the called method, where those same locations can be rewritten. This means that the calling method will access the changed parameter.

2) Tuple<T>

Example of Tuple:

Returning Multiple DataType values using Tuple<T>

using System;

class Program
{
    static void Main()
    {
    // Create four-item tuple; use var implicit type.
    var tuple = new Tuple<string, string[], int, int[]>("perl",
        new string[] { "java", "c#" },
        1,
        new int[] { 2, 3 });
    // Pass tuple as argument.
    M(tuple);
    }

    static void M(Tuple<string, string[], int, int[]> tuple)
    {
    // Evaluate the tuple's items.
    Console.WriteLine(tuple.Item1);
    foreach (string value in tuple.Item2)
    {
        Console.WriteLine(value);
    }
    Console.WriteLine(tuple.Item3);
    foreach (int value in tuple.Item4)
    {
        Console.WriteLine(value);
    }
    }
}

Output

perl
java
c#
1
2
3

NOTE: Use of Tuple is valid from Framework 4.0 and above.Tuple type is a class. It will be allocated in a separate location on the managed heap in memory. Once you create the Tuple, you cannot change the values of its fields. This makes the Tuple more like a struct.

Renelle answered 20/9, 2013 at 6:41 Comment(0)
C
3

A method taking a delegate can provide multiple values to the caller. This borrows from my answer here and uses a little bit from Hadas's accepted answer.

delegate void ValuesDelegate(int upVotes, int comments);
void GetMultipleValues(ValuesDelegate callback)
{
    callback(1, 2);
}

Callers provide a lambda (or a named function) and intellisense helps by copying the variable names from the delegate.

GetMultipleValues((upVotes, comments) =>
{
     Console.WriteLine($"This post has {upVotes} Up Votes and {comments} Comments.");
});
Cassycast answered 11/9, 2015 at 5:56 Comment(0)
H
3

From this article, you can use three options as posts above said.

KeyValuePair is quickest way.

out is at the second.

Tuple is the slowest.

Anyway, this is depend on what is the best for your scenario.

Hobart answered 23/11, 2015 at 20:15 Comment(0)
S
3

Future version of C# is going to include named tuples. Have a look at this channel9 session for the demo https://channel9.msdn.com/Events/Build/2016/B889

Skip to 13:00 for the tuple stuff. This will allow stuff like:

(int sum, int count) Tally(IEnumerable<int> list)
{
// calculate stuff here
return (0,0)
}

int resultsum = Tally(numbers).sum

(incomplete example from video)

Stationary answered 28/6, 2016 at 8:23 Comment(0)
Y
2

Just use in OOP manner a class like this:

class div
{
    public int remainder;

    public int quotient(int dividend, int divisor)
    {
        remainder = ...;
        return ...;
    }
}

The function member returns the quotient which most callers are primarily interested in. Additionally it stores the remainder as a data member, which is easily accessible by the caller afterwards.

This way you can have many additional "return values", very useful if you implement database or networking calls, where lots of error messages may be needed but only in case an error occurs.

I entered this solution also in the C++ question that OP is referring to.

Yun answered 21/11, 2014 at 10:32 Comment(0)
A
2

You could use a dynamic object. I think it has better readability than Tuple.

static void Main(string[] args){
    var obj = GetMultipleValues();
    Console.WriteLine(obj.Id);
    Console.WriteLine(obj.Name);
}

private static dynamic GetMultipleValues() {
    dynamic temp = new System.Dynamic.ExpandoObject();
    temp.Id = 123;
    temp.Name = "Lorem Ipsum";
    return temp;
}
Arwood answered 27/5, 2016 at 14:24 Comment(1)
You lose compile time type checking.Bivalve
W
1

Ways to do it:

1) KeyValuePair (Best Performance - 0.32 ns):

    KeyValuePair<int, int> Location(int p_1, int p_2, int p_3, int p_4)
    {                 
         return new KeyValuePair<int,int>(p_2 - p_1, p_4-p_3);
    }

2) Tuple - 5.40 ns:

    Tuple<int, int> Location(int p_1, int p_2, int p_3, int p_4)
    {
          return new Tuple<int, int>(p_2 - p_1, p_4-p_3);
    }

3) out (1.64 ns) or ref 4) Create your own custom class/struct

ns -> nanoseconds

Reference: multiple-return-values.

Whitleywhitlock answered 27/8, 2015 at 21:46 Comment(0)
H
1

You can also use an OperationResult

public OperationResult DoesSomething(int number1, int number2)
{
// Your Code
var returnValue1 = "return Value 1";
var returnValue2 = "return Value 2";

var operationResult = new OperationResult(returnValue1, returnValue2);
return operationResult;
}
Hint answered 13/9, 2016 at 12:21 Comment(0)
S
0

As an alternative you could set your method to void and not return anything. Instead create a public class with parameters and set them inside your method.

public class FooBar()
{
    public string foo { get; set; }
    public int bar { get; set; }
}

Then for your method try this

public void MyMethod(Foo foo, Bar bar)
{
    FooBar fooBar = new FooBar();
    fooBar.foo = "some string";
    fooBar.bar = 1;
}
Sig answered 12/9, 2021 at 20:7 Comment(0)
B
-1

you can try this

public IEnumerable<string> Get()
 {
     return new string[] { "value1", "value2" };
 }
Bout answered 16/8, 2013 at 9:38 Comment(2)
This doesn't really return multiple values. It returns a single, collection value.Ceyx
Also, why not use yield return "value1"; yield return "value2"; as to not have to explicitly create a new string[]?Boarhound

© 2022 - 2024 — McMap. All rights reserved.