Search code examples
c#typestuples

C# Define a tuple as type


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.


Solution

    • Create a record, which is a reference (C# 9+) or value type (C# 10+) which is immutable and behaves like a value type in both cases. A C# record is either a class or a struct having functionality added automatically by the compiler. See also Records (C# reference) and Use record types - C# tutorial | Microsoft Learn.
    • Create a struct, which is a value type.
    • Or declare:
      global using MyParams = System.ValueTuple<string, string>;
      
      Starting with C#12 you can create aliases for any type, i.e., also for ValueTuples:
      global using MyParams = (string key , string value);
      

    This global using must precede any other using in the file. Versions prior to C# 12 do not allow creating aliases with the C# tuple syntax (string a, string b). 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.