28

In Python I can write

def myMethod():
    #some work to find the row and col
    return (row, col)

row, col = myMethod()
mylist[row][col] # do work on this element

But in C# I find myself writing out

int[] MyMethod()
{
    // some work to find row and col
    return new int[] { row, col }
}

int[] coords = MyMethod();
mylist[coords[0]][coords[1]] //do work on this element

The Pythonic way is obivously much cleaner. Is there a way to do this in C#?

Elazar
  • 20,415
  • 4
  • 46
  • 67
jb.
  • 9,921
  • 12
  • 54
  • 90

5 Answers5

57

For .NET 4.7 and later, you can pack and unpack a ValueTuple:

(int, int) MyMethod()
{
    return (row, col);
}

(int row, int col) = MyMethod();
// mylist[row][col]

For .NET 4.6.2 and earlier, you should install System.ValueTuple:

PM> Install-Package System.ValueTuple
Elazar
  • 20,415
  • 4
  • 46
  • 67
19

There's a set of Tuple classes in .NET:

Tuple<int, int> MyMethod()
{
    // some work to find row and col
    return Tuple.Create(row, col);
}

But there's no compact syntax for unpacking them like in Python:

Tuple<int, int> coords = MyMethod();
mylist[coords.Item1][coords.Item2] //do work on this element
dtb
  • 213,145
  • 36
  • 401
  • 431
  • 3
    Note for causal reader: `Tuple<...>` is standard in .NET4+ only. –  Dec 15 '11 at 04:04
  • Note for other readers, a 2-tuple can be created in .NET < 4 (in essence) by using a KeyValuePair instead. – fabspro Mar 15 '14 at 05:33
7

An extension might get it closer to Python tuple unpacking, not more efficient but more readable (and Pythonic):

public class Extensions
{
  public static void UnpackTo<T1, T2>(this Tuple<T1, T2> t, out T1 v1, out T2 v2)
  {
    v1 = t.Item1;
    v2 = t.Item2;
  }
}

Tuple<int, int> MyMethod() 
{
   // some work to find row and col
   return Tuple.Create(row, col);
}

int row, col;    
MyMethod().UnpackTo(out row, out col);
mylist[row][col]; // do work on this element
f.cipriani
  • 3,357
  • 2
  • 26
  • 22
2

Here is a zip example with value unpacking. Here zip returns an iterator over tuples.

int[] numbers = {1, 2, 3, 4};
string[] words = {"one", "two", "three"};

foreach ((var n, var w) in numbers.Zip(words, Tuple.Create))
{
    Console.WriteLine("{0} -> {1}", n, w);
}

Output:

1 -> one
2 -> two
3 -> three
Jabba
  • 19,598
  • 6
  • 52
  • 45
2

C# is a strongly-typed language with a type system that enforces a rule that functions can have either none (void) or 1 return value. C# 4.0 introduces the Tuple class:

Tuple<int, int> MyMethod()
{
    return Tuple.Create(0, 1);
}

// Usage:
var myTuple = MyMethod();
var row = myTuple.Item1;  // value of 0
var col = myTuple.Item2;  // value of 1
Phil Klein
  • 7,344
  • 3
  • 30
  • 33
  • 15
    A strongly typed language is not restricted to returning a single value. Scheme is one example. Strong typing != static typing; Python and Scheme are strongly-but-dynamically typed. –  Dec 15 '11 at 04:06
  • 2
    This is true, it should probably be worded that C#'s type system restricts return values of functions to a single type. – Phil Klein Dec 15 '11 at 04:07
  • 3
    additionally, Go is strongly and statically typed but supports multiple return values – Ryan Haining Apr 27 '14 at 04:27