Reputation: 506
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.
Upvotes: 6
Views: 5217
Reputation: 112279
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.
Upvotes: 13
Reputation: 614
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.
Upvotes: 4
Reputation: 246
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");
Upvotes: 6