How to create named reference-type tuples?
Asked Answered
R

2

9

The following line creates a named ValueTuple:

var tuple = (a:1, b:2, c:3, d:4, e:5, f:6);  

Value types can not be passed around efficiently. Does C# 7 offer a way to create named tuples of the Tuple type?

Refreshment answered 11/6, 2017 at 21:49 Comment(5)
No, these are two different typesAppetite
How do you intend to use these tuples? You can't claim efficiency on one over the other universally... it depends on how you use it.Leucomaine
Adding to what @JeffMercado said, consider that reference types incur a GC penalty, so depending on circumstances sometimes copying a value typed structure around is faster than causing a lot of GC pressure. One specific case where this happens is if you are creating and "forgetting" objects at a high frequency, such that the GC is constantly having to run because of allocation pressure. The performance penalty you pay in those cases can sometimes be worse than a series of value type copies. Only a profiler can tell you with certainty though.Tactic
@ ozeanix I understand the reasoning for ValueTuple - created often, used once - but most of the time you just want to use Tuples as simple containers with the convenience of the syntax, for example as a data package in class properties public (int a, int b) Data;Refreshment
Then there's no use for you to be preferring Tuple over ValueTuple then. Use what the language provides for you first until you could determine that you could benefit from using Tuple. Judging by what you have shown here, you don't know that.Leucomaine
C
4

If you mean if there's a way to attach other names to the properties of System.Tuple<...> instances, no there isn't.

Depending on why you want it, you might get around it by converting System.Tuple<...> instances to System.ValueTuple<...> instances using the ToValueTuple overloads in TupleExtensions and back using the ToTuple overloads.

If you don't really need the tuples, you can deconstruct them into discrete variables using the Deconstruct overloads or the var (v1, .., vn) = tuple deconstruction syntax.

Cobble answered 11/6, 2017 at 22:42 Comment(2)
Tuple has properties Itemn, named tuples are, well, named. It's not easy to implementAppetite
Yes, @Brandon, it would be easy to implement and it would have been easier to not introduce a new type for tuples. So it looks. But if you feel that way, chances are you're doing the wrong thing.Cobble
P
-1

Not sure what the problem is; everything works as expected for me for passing the new ValueTuple<T> with out, ref, and the new ref locals.

I'm using .NET 4.7 and have my C#7 compiler set to "latest" in the .csproj settings "Advanced..." button.

Demonstration functions (and data):

static (int, int) g = (1, 2);

static void SetValues(int a, int b, ref (int, int) tt) => tt = (a, b);

static void SetValuesOut(int a, int b, out (int, int) tt) => tt = (a, b);

static ref (int, int) GetKnownTuple() => ref g;

static ref (int, int) SelectRef(
    int ix, 
    ref (int, int) x, 
    ref (int, int) y, 
    ref (int, int) z)
{
    if (ix == 0) return ref x;
    if (ix == 1) return ref y;
    return ref z;
}

Usage Examples:

static void demo_usages() {

/// use 'ref return' to initialize a new 'ref local' tuple 'aa'
ref (int, int) aa = ref GetKnownTuple();

/// or use the same function without 'ref' to create a local COPY 'bb'
var bb = GetKnownTuple();

/// use 'ref' parameter to modify values of local copy 'bb' ('aa/g' are not altered)
SetValues(3, 4, ref bb);

/// deconstruction of 'ref local' tuple; reads values from referent 'g' (1, 2)
(int x, int y) = aa;

/// 'ref local' reference to a local tuple copy
ref (int, int) dd = ref bb;

/// use 'out' parameter to construct a new (non-'ref') local tuple 'cc'
SetValuesOut(y, x, out (int, int) cc);

/// ...or use 'out' with 'ref local' to wholly replace existing referent ('g' here)
SetValuesOut(5, 6, out aa);

/// 'ref return' function can also be used as assignment l-value...
GetKnownTuple() = (7, 8);

/// ('aa/g' are altered; locals 'bb' and 'cc' remain unchanged)

/// ...or assign a referent via 'ref local' variable (changes 'g' again)
aa = (9, 10);

/// conditional assignment via 'ref return'  (changes 'g' again)
SelectRef(0, ref aa, ref bb, ref cc) = (11, 12);

}

It should be clear that much more is possible, but all cannot be shown here since the OP's question does not get into too many specific further requirements.

Piceous answered 3/9, 2017 at 0:57 Comment(2)
this was very detailed and helpful explanation, thank youPolycotyledon
You are not answering the question, that is just gibberish.Windom

© 2022 - 2024 — McMap. All rights reserved.