Better naming in Tuple classes than "Item1", "Item2"
Asked Answered
J

21

338

Is there a way to use a Tuple class, but supply the names of the items in it?

For example:

public Tuple<int, int, int int> GetOrderRelatedIds()

That returns the ids for OrderGroupId, OrderTypeId, OrderSubTypeId and OrderRequirementId.

It would be nice to let the users of my method know which is which. (When you call the method, the results are result.Item1, result.Item2, result.Item3, result.Item4. It is not clear which one is which.)

(I know I could just create a class to hold all these Ids, but it these Ids already have their own classes they live in and making a class for this one method's return value seems silly.)

Johnsson answered 12/10, 2011 at 20:10 Comment(3)
You're gonna have to roll your own - Tuple is very generic, so that's all you getNogas
NO you cannot do like that , see this link for more information msdn.microsoft.com/en-us/vcsharp/ee957397Smorgasbord
I would venture to say that using a Tuple as a public facing datatype for your api may not be recommended. I typically use Tuple for short lived internal things not as a return value of a API.Kilovolt
N
496

In C# 7.0 (Visual Studio 2017) there is a new construction to do that:

(string first, string middle, string last) LookupName(long id)
Nauru answered 13/10, 2016 at 6:42 Comment(7)
The syntax is List<(int first, int second)>. I had to download the System.ValueTuple package from NuGet to get it to work in Visual Studio 2017.Antitrades
To create the value return (first: first, middle: middle, last: last);Clair
or only: return (first, middle, last); in .NET 4.7.1 (not sure for 4.7.0)Epos
A lot of interesting details about the new tuple types, tuple literals and tuple deconstruction in C# 7 can be found here: blogs.msdn.microsoft.com/dotnet/2017/03/09/…Tresa
in order to use it you will need to add System.ValueTuple nuget packageEntreaty
It should be noted that C# 7's ValueTuple, while usually great, is a mutable value type (struct), while Tuple is an immutable reference type (class). As far as I know, there's no way to get a reference type Tuple with friendly item names.Darrelldarrelle
Be aware of the EF limitations: https://mcmap.net/q/98146/-better-naming-in-tuple-classes-than-quot-item1-quot-quot-item2-quotCustomer
T
53

Up to C# 7.0, there was no way to do this short of defining your own type.

Tartaric answered 12/10, 2011 at 20:12 Comment(2)
After C# 7 is released, it will be possible to do this: msdn.microsoft.com/en-us/magazine/mt595758.aspxCyclo
Beware that System.Tuple and System.ValueTuple (on which the 'C# 7.0 Tuples' are based) are two completely different concepts: - System.ValueTuple types are value types / System.Tuple types are reference types. - System.ValueTuple types are mutable / System.Tuple types are immutable. - Data members of System.ValueTuple types are fields / Data members of System.Tuple types are properties.Lazare
B
39

Here is an overly complicated version of what you are asking:

class MyTuple : Tuple<int, int>
{
    public MyTuple(int one, int two)
        :base(one, two)
    {

    }

    public int OrderGroupId { get{ return this.Item1; } }
    public int OrderTypeId { get{ return this.Item2; } }

}

Why not just make a class?

Beachhead answered 12/10, 2011 at 20:22 Comment(5)
would struct be better in this case instead of Class?Renelle
The slight advantage I see of this is that it automatically implements the equals operator, checking that 2 instances are equal if the items are all equal.Questionnaire
Another drawback to this approach is that Item1 and Item2 are still public properties on MyTupleThumbtack
@Renelle Tuple themselves are classes, so if you want to directly inherit from Tuple<T, T2> you can't be a struct.Biconcave
I may be wrong but I mostly use tuple wherever I want to return an object but doesn't want to define a specific class..Posthaste
O
38

Reproducing my answer from this post as it is a better fit here.

Starting C# v7.0, it is now possible to name the tuple properties which earlier used to default to names like Item1, Item2 and so on.

Naming the properties of Tuple Literals:

var myDetails = (MyName: "Foo", MyAge: 22, MyFavoriteFood: "Bar");
Console.WriteLine($"Name - {myDetails.MyName}, Age - {myDetails.MyAge}, Passion - {myDetails.MyFavoriteFood}");

The output on console:

Name - Foo, Age - 22, Passion - Bar

Returning Tuple (having named properties) from a method:

static void Main(string[] args)
{
    var empInfo = GetEmpInfo();
    Console.WriteLine($"Employee Details: {empInfo.firstName}, {empInfo.lastName}, {empInfo.computerName}, {empInfo.Salary}");
}

static (string firstName, string lastName, string computerName, int Salary) GetEmpInfo()
{
    //This is hardcoded just for the demonstration. Ideally this data might be coming from some DB or web service call
    return ("Foo", "Bar", "Foo-PC", 1000);
}

The output on console:

Employee Details: Foo, Bar, Foo-PC, 1000

Creating a list of Tuples having named properties

var tupleList = new List<(int Index, string Name)>
{
    (1, "cow"),
    (5, "chickens"),
    (1, "airplane")
};

foreach (var tuple in tupleList)
    Console.WriteLine($"{tuple.Index} - {tuple.Name}");

Output on console:

1 - cow  
5 - chickens  
1 - airplane

Note: Code snippets in this post are using string interpolation feature of C# v6 as detailed here.

Ollie answered 30/5, 2018 at 6:39 Comment(1)
The example in the question is using the System.Tuple class to create a Tuple object which is different than using the parenthesis syntax to create a tuple. Your answer applies to the latter type of tuple but not the System.Tuple object.Abdul
A
23

TL:DR -> System.ValueTuples can have custom names for fields, System.Tuples cannot.

Just to clarify, there are 2 different types of tuples in C# 7.0 and later. Before that there was only 1 single type of tuple available.

System.Tuple (this is the original type of tuple that existed pre C# 7) and System.ValueTuple (tuple type that was added in C# 7)

When you declare a tuple via the Tuple<...> class:

public Tuple<int, string, int> GetUserInfo();

You're declaring a Tuple object data type.

When you declare a tuple via parenthesis:

public (int id, string name, int age) GetUserInfo();

You're declaring a ValueTuple value data type.

Each one functions and behaves differently. In your question, your method returns a System.Tuple object.

Unfortunately, Tuple objects created via the System.Tuple class have no built in functionality to give each property a custom name. They always default to ItemN depending on how many properties they contain.

System.ValueTuple values on the other hand can contain custom named fields.

For more info, you can refer to Tuple types (C# reference) and/or the links to each class above. But essentially some of the key differences of the 2 different types of tuples that the documentation highlights are:

C# tuples, which are backed by System.ValueTuple types, are different from tuples that are represented by System.Tuple types. The main differences are as follows:

  • System.ValueTuple types are value types. System.Tuple types are reference types.
  • System.ValueTuple types are mutable. System.Tuple types are immutable.
  • Data members of System.ValueTuple types are fields. Data members of System.Tuple types are properties.

So if your method needs to return a System.Tuple object or you desire the behavior of that type of object more, then as of writing this, you can't achieve what you want. However, if your method can return a System.ValueTuple value, then you can give it custom named fields in the returned value.

Abdul answered 20/1, 2022 at 4:55 Comment(4)
why not capitalize tuple fields?Mcdaniel
Just a preference thing is all. They certainly can be capitalized if you'd like.Abdul
to me in code it would look similar to how you'd call a property on a class...?Mcdaniel
Depending on how the tuple is used can vary. In the case where the tuple is an object with properties, it's generally more conventional to have them capitalized. (string Name, int Age) user = ("Marvin", 400);. However if the tuple is being used to deconstruct something such as (int anInt, string aString) = (45, "MEEP"); then it's more conventional to have them lower cased (like a variable name).Abdul
B
15

With .net 4 you could perhaps look at the ExpandoObject, however, don't use it for this simple case as what would have been compile-time errors become run-time errors.

class Program
{
    static void Main(string[] args)
    {
        dynamic employee, manager;

        employee = new ExpandoObject();
        employee.Name = "John Smith";
        employee.Age = 33;

        manager = new ExpandoObject();
        manager.Name = "Allison Brown";
        manager.Age = 42;
        manager.TeamSize = 10;

        WritePerson(manager);
        WritePerson(employee);
    }
    private static void WritePerson(dynamic person)
    {
        Console.WriteLine("{0} is {1} years old.",
                          person.Name, person.Age);
        // The following statement causes an exception
        // if you pass the employee object.
        // Console.WriteLine("Manages {0} people", person.TeamSize);
    }
}
// This code example produces the following output:
// John Smith is 33 years old.
// Allison Brown is 42 years old.

Something else worth mentioning is an anonymous type for within a method, but you need to create a class if you want to return it.

var MyStuff = new
    {
        PropertyName1 = 10,
        PropertyName2 = "string data",
        PropertyName3 = new ComplexType()
    };
Bromate answered 12/10, 2011 at 20:14 Comment(0)
U
6

MichaelMocko Answered is great,

but I want to add a few things which I had to figure out

(string first, string middle, string last) LookupName(long id)

above Line will give you compile-time error if you are using .net framework < 4.7

So if you have a project that is using .net framework < 4.7 and still you want to use ValueTuple than workAround would be installing this NuGet package

Update:

Example of returning Named tuple from a method and using it

public static (string extension, string fileName) GetFile()
{
    return ("png", "test");
}

Using it

var (extension, fileName) = GetFile();

Console.WriteLine(extension);
Console.WriteLine(fileName);
Unbolt answered 1/5, 2019 at 14:21 Comment(0)
C
5

Just to add to @MichaelMocko answer. Tuples have couple of gotchas at the moment:

You can't use them in EF expression trees

Example:

public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        // Selecting as Tuple
        .Select(person => (person.Name, person.Surname))
        .First();
}

This will fail to compile with "An expression tree may not contain a tuple literal" error. Unfortunately, the expression trees API wasn't expanded with support for tuples when these were added to the language.

Track (and upvote) this issue for the updates: https://github.com/dotnet/roslyn/issues/12897

To get around the problem, you can cast it to anonymous type first and then convert the value to tuple:

// Will work
public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        .Select(person => new { person.Name, person.Surname })
        .ToList()
        .Select(person => (person.Name, person.Surname))
        .First();
}

Another option is to use ValueTuple.Create:

// Will work
public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        .Select(person => ValueTuple.Create(person.Name, person.Surname))
        .First();
}

References:

You can't deconstruct them in lambdas

There's a proposal to add the support: https://github.com/dotnet/csharplang/issues/258

Example:

public static IQueryable<(string name, string surname)> GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        .Select(person => ValueTuple.Create(person.Name, person.Surname));
}

// This won't work
ctx.GetPersonName(id).Select((name, surname) => { return name + surname; })

// But this will
ctx.GetPersonName(id).Select(t => { return t.name + t.surname; })

References:

They won't serialize nicely

using System;
using Newtonsoft.Json;

public class Program
{
    public static void Main() {
        var me = (age: 21, favoriteFood: "Custard");
        string json = JsonConvert.SerializeObject(me);

        // Will output {"Item1":21,"Item2":"Custard"}
        Console.WriteLine(json); 
    }
}

Tuple field names are only available at compile time and are completely wiped out at runtime.

References:

Customer answered 12/6, 2020 at 10:8 Comment(0)
K
5

As of today, it's this simple. Instead of using the Tuple keyword

public Tuple<int, int, int int> GetOrderRelatedIds()

Use this.

public (int alpha, int beta, int candor) GetOrderRelatedIds()

Get the values like this.

var a = GetOrderRelatedIds();
var c = a.alpha;
Krein answered 6/7, 2021 at 10:18 Comment(4)
Tuple<int, int, int int> and (int alpha, int beta, int candor) are different types of tuples that have very different behaviors and properties. What your suggesting may very well be a solution to the asker's question, however it should be noted that there may be side affects by switching from Tuple<int, int, int int> to (int alpha, int beta, int candor).Abdul
@Abdul I do not understand what you are talking about. OP asked for tuples which allow names instead of item1 and item2, this is what I have provided.Krein
Your answer does provide a potential solution, but with caveats that could be worth mentioning is all. (int alpha, int beta, int candor) is not simply the same thing as Tuple<int, int, int> except with named properties. They behave differently and there might be a reason the OP is using one over the other.Abdul
@Abdul I think the obvious reason is because this type of tuple declaration was not available to C# yet at the time this question was askedKrein
P
3

No, you can't name the tuple members.

The in-between would be to use ExpandoObject instead of Tuple.

Pappose answered 12/10, 2011 at 20:15 Comment(0)
L
2

If the types of your items are all different, here is a class I made to get them more intuitively.

The usage of this class:

var t = TypedTuple.Create("hello", 1, new MyClass());
var s = t.Get<string>();
var i = t.Get<int>();
var c = t.Get<MyClass>();

Source code:

public static class TypedTuple
{
    public static TypedTuple<T1> Create<T1>(T1 t1)
    {
        return new TypedTuple<T1>(t1);
    }

    public static TypedTuple<T1, T2> Create<T1, T2>(T1 t1, T2 t2)
    {
        return new TypedTuple<T1, T2>(t1, t2);
    }

    public static TypedTuple<T1, T2, T3> Create<T1, T2, T3>(T1 t1, T2 t2, T3 t3)
    {
        return new TypedTuple<T1, T2, T3>(t1, t2, t3);
    }

    public static TypedTuple<T1, T2, T3, T4> Create<T1, T2, T3, T4>(T1 t1, T2 t2, T3 t3, T4 t4)
    {
        return new TypedTuple<T1, T2, T3, T4>(t1, t2, t3, t4);
    }

    public static TypedTuple<T1, T2, T3, T4, T5> Create<T1, T2, T3, T4, T5>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
    {
        return new TypedTuple<T1, T2, T3, T4, T5>(t1, t2, t3, t4, t5);
    }

    public static TypedTuple<T1, T2, T3, T4, T5, T6> Create<T1, T2, T3, T4, T5, T6>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
    {
        return new TypedTuple<T1, T2, T3, T4, T5, T6>(t1, t2, t3, t4, t5, t6);
    }

    public static TypedTuple<T1, T2, T3, T4, T5, T6, T7> Create<T1, T2, T3, T4, T5, T6, T7>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
    {
        return new TypedTuple<T1, T2, T3, T4, T5, T6, T7>(t1, t2, t3, t4, t5, t6, t7);
    }

    public static TypedTuple<T1, T2, T3, T4, T5, T6, T7, T8> Create<T1, T2, T3, T4, T5, T6, T7, T8>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
    {
        return new TypedTuple<T1, T2, T3, T4, T5, T6, T7, T8>(t1, t2, t3, t4, t5, t6, t7, t8);
    }

}

public class TypedTuple<T>
{
    protected Dictionary<Type, object> items = new Dictionary<Type, object>();

    public TypedTuple(T item1)
    {
        Item1 = item1;
    }

    public TSource Get<TSource>()
    {
        object value;
        if (this.items.TryGetValue(typeof(TSource), out value))
        {
            return (TSource)value;
        }
        else
            return default(TSource);
    }

    private T item1;
    public T Item1 { get { return this.item1; } set { this.item1 = value; this.items[typeof(T)] = value; } }
}

public class TypedTuple<T1, T2> : TypedTuple<T1>
{
    public TypedTuple(T1 item1, T2 item2)
        : base(item1)
    {
        Item2 = item2;
    }

    private T2 item2;
    public T2 Item2 { get { return this.item2; } set { this.item2 = value; this.items[typeof(T2)] = value; } }
}

public class TypedTuple<T1, T2, T3> : TypedTuple<T1, T2>
{
    public TypedTuple(T1 item1, T2 item2, T3 item3)
        : base(item1, item2)
    {
        Item3 = item3;
    }

    private T3 item3;
    public T3 Item3 { get { return this.item3; } set { this.item3 = value; this.items[typeof(T3)] = value; } }
}

public class TypedTuple<T1, T2, T3, T4> : TypedTuple<T1, T2, T3>
{
    public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4)
        : base(item1, item2, item3)
    {
        Item4 = item4;
    }

    private T4 item4;
    public T4 Item4 { get { return this.item4; } set { this.item4 = value; this.items[typeof(T4)] = value; } }
}

public class TypedTuple<T1, T2, T3, T4, T5> : TypedTuple<T1, T2, T3, T4>
{
    public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5)
        : base(item1, item2, item3, item4)
    {
        Item5 = item5;
    }

    private T5 item5;
    public T5 Item5 { get { return this.item5; } set { this.item5 = value; this.items[typeof(T5)] = value; } }
}

public class TypedTuple<T1, T2, T3, T4, T5, T6> : TypedTuple<T1, T2, T3, T4, T5>
{
    public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6)
        : base(item1, item2, item3, item4, item5)
    {
        Item6 = item6;
    }

    private T6 item6;
    public T6 Item6 { get { return this.item6; } set { this.item6 = value; this.items[typeof(T6)] = value; } }
}

public class TypedTuple<T1, T2, T3, T4, T5, T6, T7> : TypedTuple<T1, T2, T3, T4, T5, T6>
{
    public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7)
        : base(item1, item2, item3, item4, item5, item6)
    {
        Item7 = item7;
    }

    private T7 item7;
    public T7 Item7 { get { return this.item7; } set { this.item7 = value; this.items[typeof(T7)] = value; } }
}

public class TypedTuple<T1, T2, T3, T4, T5, T6, T7, T8> : TypedTuple<T1, T2, T3, T4, T5, T6, T7>
{
    public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8)
        : base(item1, item2, item3, item4, item5, item6, item7)
    {
        Item8 = item8;
    }

    private T8 item8;
    public T8 Item8 { get { return this.item8; } set { this.item8 = value; this.items[typeof(T8)] = value; } }
}
Literary answered 24/1, 2014 at 2:19 Comment(1)
This seems like a lot of work for little to no payoff. It has an unintuitive limitation (no duplicate types), and I find the idea of retrieving a value by only its type alone incredibly unintuitive and cannot think of a practical use case for it. This is the equivalent of making a data table for employees, then deciding to retrieve employees by their first name (as opposed to a unique key) and subsequently requiring all employees to have different first names. This isn't a solution to a problem, it's using a solution at the cost of creating an extra problem.Sonata
N
2
(double, int) t1 = (4.5, 3);
Console.WriteLine($"Tuple with elements {t1.Item1} and {t1.Item2}.");
// Output:
// Tuple with elements 4.5 and 3.

(double Sum, int Count) t2 = (4.5, 3);
Console.WriteLine($"Sum of {t2.Count} elements is {t2.Sum}.");
// Output:
// Sum of 3 elements is 4.5.

From Docs: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-tuples

Neat answered 28/10, 2020 at 14:35 Comment(0)
M
1

This is very annoying and I expect future versions of C# will address this need. I find the easiest work around to be either use a different data structure type or rename the "items" for your sanity and for the sanity of others reading your code.

Tuple<ApiResource, JSendResponseStatus> result = await SendApiRequest();
ApiResource apiResource = result.Item1;
JSendResponseStatus jSendStatus = result.Item2;
Mandel answered 28/10, 2016 at 19:47 Comment(0)
C
1

Why not using a multiple returns instead of using tuple

var handler = GenerateFromMethod1(hits);
Process(handler.string1, handler.string1);

private static (string string1, string string2) GenerateFromMethod1()
{

}
Crucial answered 27/7, 2022 at 18:24 Comment(0)
C
0

I think I would create a class but another alternative is output parameters.

public void GetOrderRelatedIds(out int OrderGroupId, out int OrderTypeId, out int OrderSubTypeId, out int OrderRequirementId)

Since your Tuple only contains integers you could represent it with a Dictionary<string,int>

var orderIds = new Dictionary<string, int> {
    {"OrderGroupId", 1},
    {"OrderTypeId", 2},
    {"OrderSubTypeId", 3},
    {"OrderRequirementId", 4}.
};

but I don't recommend that either.

Chelyabinsk answered 12/10, 2011 at 21:4 Comment(0)
T
0

Why is everyone making life so hard. Tuples are for rather temporary data processing. Working with Tuples all the time will make the code very hard to understand at some point. Creating classes for everything could eventually bloat your project.

It's about balance, however...

Your problem seems to be something you would want a class for. And just for the sake of completeness, this class below also contains constructors.


This is the proper pattern for

  • A custom data type
    • with no further functionality. Getters and setters can also be expanded with code, getting/setting private members with the name pattern of "_orderGroupId", while also executing functional code.
  • Including constructors. You can also choose to include just one constructor if all properties are mandatory.
  • If you want to use all constructors, bubbling like this is the proper pattern to avoid duplicate code.

public class OrderRelatedIds
{
    public int OrderGroupId { get; set; }
    public int OrderTypeId { get; set; }
    public int OrderSubTypeId { get; set; }
    public int OrderRequirementId { get; set; }

    public OrderRelatedIds()
    {
    }
    public OrderRelatedIds(int orderGroupId)
        : this()
    {
        OrderGroupId = orderGroupId;
    }
    public OrderRelatedIds(int orderGroupId, int orderTypeId)
        : this(orderGroupId)
    {
        OrderTypeId = orderTypeId;
    }
    public OrderRelatedIds(int orderGroupId, int orderTypeId, int orderSubTypeId)
        : this(orderGroupId, orderTypeId)
    {
        OrderSubTypeId = orderSubTypeId;
    }
    public OrderRelatedIds(int orderGroupId, int orderTypeId, int orderSubTypeId, int orderRequirementId)
        : this(orderGroupId, orderTypeId, orderSubTypeId)
    {
        OrderRequirementId = orderRequirementId;
    }
}

Or, if you want it really simple: You can also use type initializers:

OrderRelatedIds orders = new OrderRelatedIds
{
    OrderGroupId = 1,
    OrderTypeId = 2,
    OrderSubTypeId = 3,
    OrderRequirementId = 4
};

public class OrderRelatedIds
{
    public int OrderGroupId;
    public int OrderTypeId;
    public int OrderSubTypeId;
    public int OrderRequirementId;
}
Toxoplasmosis answered 18/8, 2016 at 18:26 Comment(0)
P
0

I would write the Item names in the summay.. so by hovering over the function helloworld() the text will say hello = Item1 and world = Item2

 helloworld("Hi1,Hi2");

/// <summary>
/// Return hello = Item1 and world Item2
/// </summary>
/// <param name="input">string to split</param>
/// <returns></returns>
private static Tuple<bool, bool> helloworld(string input)
{
    bool hello = false;
    bool world = false;
    foreach (var hw in input.Split(','))
    {
        switch (hw)
        {
            case "Hi1":
                hello= true;
                break;
            case "Hi2":
                world= true;
                break;
        }

    }
    return new Tuple<bool, bool>(hello, world);
}
Pammy answered 12/10, 2016 at 13:0 Comment(0)
A
0

Hey if you wind up having issues with the Dynamic or Object casting removing your Named Tuple parameters, just create a function that passes the dynamic/object cast pointer by reference and recasts it upon return...got this bad-boy working...

Attitude answered 24/11, 2023 at 11:13 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Brianabriand
A
0

If you need a small class to store data (not a structure like ValueTuple), then starting from C# 9 you can use record instead of the Tuple class

For example:

internal class Program
{
    record OrderInfo(int OrderGroupId, int OrderTypeId, int OrderSubTypeId, int OrderRequirementId);
    
    private static void Main(string[] args)
    {
        OrderInfo order_info = new OrderInfo(0, 1, 2, 3);
        //order_info.OrderGroupId = 1;//you can't change the value of init-only property
        Console.WriteLine(order_info.OrderSubTypeId);//2
    }
}
Alwyn answered 12/4 at 13:9 Comment(0)
A
-1

You Can write a class that contains the Tuple.

You need to override the Equals and GetHashCode functions

and the == and != operators.

class Program
{
    public class MyTuple
    {
        private Tuple<int, int> t;

        public MyTuple(int a, int b)
        {
            t = new Tuple<int, int>(a, b);
        }

        public int A
        {
            get
            {
                return t.Item1;
            }
        }

        public int B
        {
            get
            {
                return t.Item2;
            }
        }

        public override bool Equals(object obj)
        {
            return t.Equals(((MyTuple)obj).t);
        }

        public override int GetHashCode()
        {
            return t.GetHashCode();
        }

        public static bool operator ==(MyTuple m1, MyTuple m2)
        {
            return m1.Equals(m2);
        }

        public static bool operator !=(MyTuple m1, MyTuple m2)
        {
            return !m1.Equals(m2);
        }
    }

    static void Main(string[] args)
    {
        var v1 = new MyTuple(1, 2);
        var v2 = new MyTuple(1, 2);

        Console.WriteLine(v1 == v2);

        Dictionary<MyTuple, int> d = new Dictionary<MyTuple, int>();
        d.Add(v1, 1);

        Console.WriteLine(d.ContainsKey(v2));
    }
}

will return:

True

True

Adventure answered 10/1, 2016 at 13:2 Comment(3)
If you already implemented a class for this data type, why do you declare a Tuple for the underlying data instead of just properties?Toxoplasmosis
I want to use the tuple attribute that it comper by value in Equals functionAdventure
That may be a bonus. But on the other hand you basically created a class with properties that range from Item1 to ItemX. I would choose proper naming and more code in Equals() over using a tuple.Toxoplasmosis
A
-2

C# 7 tuple example

var tuple = TupleExample(key, value);

     private (string key1, long value1) ValidateAPIKeyOwnerId(string key, string value)
            {
                return (key, value);
            }
      if (!string.IsNullOrEmpty(tuple.key1) && tuple.value1 > 0)
          {
                    //your code

                }     
Abercrombie answered 23/4, 2020 at 14:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.