Home > Software engineering >  C# Define a tuple as type
C# Define a tuple as type

Time:08-01

Is there a way in C# to define a custom type which holds a tuple? e.g.:

Type MyParams Tuple<string, string> ?

Motive: I have the following function in a parent class:

protected virtual IEnumerable<(string, string)> GetConfigs()

that will be overridden by each child class. I'm looking for a way to define that tuple as type to declare the return type as IEnumerable<Params> instead of duplicating the tuple.

CodePudding user response:

  • Create a record, which is a reference (C# 9 ) or value type (C# 10 ).
  • Create a struct, which is a value type.
  • Or declare:
    global using MyParams = System.ValueTuple<string, string>;
    

This global using must precede any other using in the file. You cannot use the C# tuple syntax (string a, string b) here. Therefore, you will have to access the tuple elements with t.Item1, t.Item2 etc.

If you omit the global keyword (C# 10 ), the scope of the directive is limited to the current file.

Now you can declare the method as

protected virtual IEnumerable<MyParams> GetConfigs()
{
   ...
}

Note; however, that this global using is only known in the current assembly!

Therefore, its use in a public API of a class library is limited.

It is still possible to access members of this library using this type, so.

Having this declaration in one assembly

global using MyParams = System.ValueTuple<string, string>;

namespace MyLibrary;

public class Class1
{
    public MyParams p = ("hello", "world");
}

You can write this in another assembly referencing the first one:

var obj = new MyLibrary.Class1();
Console.WriteLine(obj.p);

But a declaration like MyLibrary.MyParams p; is not possible in the other assembly.

CodePudding user response:

Firstly, I would definitely recommend having a proper defined type given it's for an API (although in fairness I have a dislike for tuples anyway). Something like this might do, with type conversions to/from a (string, string):

public struct SuitableTypeName
{
    public string SomeName;
    public string SomeDifferentName;

    public SuitableTypeName(string someName, string someDifferentName)
    {
        SomeName = someName;
        SomeDifferentName = someDifferentName;
    }

    public static implicit operator (string, string)(SuitableTypeName name)
    {
        return (name.SomeName, name.SomeDifferentName);
    }

    public static explicit operator SuitableTypeName ((string, string) tuple)
    {
        return new SuitableTypeName(tuple.Item1, tuple.Item2);
    }
}

Note that depending you might consider using a class rather than a struct. In this example it's a mutable struct which may lead to confusion/unexpected behavior, so if you're worried about that you could also make it immutable. Also, some groups have very strong feelings about mutable structs for some reason, so if you're working in a group and decide to use it as-is you may want to check your coding standards or clear it with the others.

CodePudding user response:

What you're looking for is called alias using directive. However, according to the documentation you can define it with global scope starting from C# 10. Otherwise, you need to make an alias in every file when you want to use it.

using MyParams = System.Tuple<string, string>;

usage:

var foo = new MyParams("foo", "baz");
  • Related