c# multi assignment

int a, b, n;
...
(a, b) = (2, 3);
// 'a' is now 2 and 'b' is now 3

This sort of thing would be really helpfull in C#. In this example 'a' and 'b' arn't encapsulated together such as the X and Y of a position might be. Does this exist in some form?

Below is a less trivial example.

(a, b) = n == 4 ? (2, 3) : (3, n % 2 == 0 ? 1 : 2);

Adam Maras shows in the comments that:

var result = n == 4 ? Tuple.Create(2, 3) : Tuple.Create(3, n % 2 == 0 ? 1 : 2);

Sort of works for the example above however as he then points out it creates a new truple instead of changing the specified values.

Eric Lippert asks for use cases, therefore perhaps:

(a, b, c) = (c, a, b); // swap or reorder on one line
(x, y) = move((x, y), dist, heading);
byte (a, b, c, d, e) = (5, 4, 1, 3, 2);
graphics.(PreferredBackBufferWidth, PreferredBackBufferHeight) = 400;

notallama also has use cases, they are in his answer below.

Answers


We have considered supporting a syntactic sugar for tuples but it did not make the bar for C# 4.0. It is unlikely to make the bar for C# 5.0; the C# 5.0 team is pretty busy with getting async/await working right. We will consider it for hypothetical future versions of the language.

If you have a really solid usage case that is compelling, that would help us prioritize the feature.


use case:

it'd be really nice for working with IObservables, since those have only one type parameter. you basically want to subscribe with arbitrary delegates, but you're forced to use Action, so that means if you want multiple parameters, you have to either use tuples, or create custom classes for packing and unpacking parameters.

example from a game:

public IObservable<Tuple<GameObject, DamageInfo>> Damaged ...

void RegisterHitEffects() {
    (from damaged in Damaged
     where damaged.Item2.amount > threshold
     select damaged.Item1)
    .Subscribe(DoParticleEffect)
    .AddToDisposables();
}

becomes:

void RegisterHitEffects() {
    (from (gameObject, damage) in Damaged
     where damage.amount > threshold
     select gameObject)
    .Subscribe(DoParticleEffect)
    .AddToDisposables();
}

which i think is cleaner.

also, presumably IAsyncResult will have similar issues when you want to pass several values. sometimes it's cumbersome to create classes just to shuffle a bit of data around, but using tuples as they are now reduces code clarity. if they're used in the same function, anonymous types fit the bill nicely, but they don't work if you need to pass data between functions.

also, it'd be nice if the sugar worked for generic parameters, too. so:

IEnumerator<(int, int)>

would desugar to

IEnumerator<Tuple<int,int>>

The behavior that you're looking for can be found in languages that have support or syntactic sugar for tuples. C# is not among these langauges; while you can use the Tuple<...> classes to achieve similar behavior, it will come out very verbose (not clean like you're looking for.)


The closest structure I can think of is the Tuple class in version 4.0 of the framework.


As others already wrote, C# 4 Tuples are a nice addition, but nothing really compelling to use as long as there aren't any unpacking mechanisms. What I really demand of any type I use is clarity of what it describes, on both sides of the function protocol (e.g. caller, calle sides)... like

Complex SolvePQ(double p, double q)
{
    ...
    return new Complex(real, imag);
}
...
var solution = SolvePQ(...);
Console.WriteLine("{0} + {1}i", solution.Real, solution.Imaginary);

This is obvious and clear at both caller and callee side. However this

Tuple<double, double> SolvePQ(double p, double q)
{
    ...
    return Tuple.Create(real, imag);
}
...
var solution = SolvePQ(...);
Console.WriteLine("{0} + {1}i", solution.Item1, solution.Item2);

Doesn't leave the slightest clue about what that solution actually is (ok, the string and the method name make it pretty obvious) at the call site. Item1 and Item2 are of the same type, which renders tooltips useless. The only way to know for certain is to "reverse engineer" your way back through SolvePQ.

Obivously, this is far fetched and everyone doing serious numerical stuff should have a Complex type (like that in the BCL). But everytime you get split results and you want give those results distinct names for the sake of readability, you need tuple unpacking. The rewritten last two lines would be:

var (real, imaginary) = SolvePQ(...); // or var real, imaginary = SolvePQ(...);
Console.WriteLine("{0} + {1}i", real, imaginary);

This leaves no room for confusion, except for getting used to the syntax.


Creating a set of Unpack<T1, T2>(this Tuple<T1, T2>, out T1, out T2) methods would be a more idiomatic c# way of doing this.

Your example would then become

int a, b, n;
...
Tuple.Create(2, 3).Unpack(out a, out b);
// 'a' is now 2 and 'b' is now 3

which is no more complex than your proposal, and a lot clearer.


Deconstruction was introduced in C# 7.0: https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/#user-content-deconstruction


Need Your Help

Simulate memory warnings from the code, possible?

iphone memory memory-management ios-simulator

I know i can simulate a memory warning on the simulator by selecting 'Simulate Memory Warning' from the drop down menu of the iPhone Simulator. I can even make a hot key for that.

sudo pecl install apc returns error

php pear apc pecl

I run the command: sudo pecl install apc