I search in StackOverflow, don't find any articles or anything related to that.
For example, the following example describes array of ValueTuple
(string CategoryName, params string[] Properties)[] MyArrayValueTupleParameter // Compile-Time Syntax error
Note that the previous example used as a parameter. not a variable.
But only string[]
works without params? Did I missed something here or is it not supported by default?
At a glance:
This Works
void ShowAppearanceCategories((string CategoryName, string[] Properties)[] VisibleCategories)
{
foreach (var Row in PropertyGridControl.Rows)
{
var VisibleCategory = VisibleCategories.FirstOrDefault(x => x.CategoryName == Row.Name);
if (VisibleCategory != default)
{
foreach (var ChildRow in Row.ChildRows)
{
if (VisibleCategory.Properties.Any(x => ChildRow.Name.Contains(x)))
{
ChildRow.Visible = false;
}
}
}
else
{
Row.Visible = false;
}
}
}
This Doesn't Work
void ShowAppearanceCategories((string CategoryName, params string[] Properties)[] VisibleCategories) // Syntax-Error
{
foreach (var Row in PropertyGridControl.Rows)
{
var VisibleCategory = VisibleCategories.FirstOrDefault(x => x.CategoryName == Row.Name);
if (VisibleCategory != default)
{
foreach (var ChildRow in Row.ChildRows)
{
if (VisibleCategory.Properties.Any(x => ChildRow.Name.Contains(x)))
{
ChildRow.Visible = false;
}
}
}
else
{
Row.Visible = false;
}
}
}
A parameter array is a very specific language feature that is only applicable to method parameters. A value tuple is a struct with variable length generic parameters and has been given a special syntax for initialization and usage (most of which are just smoke an mirrors).
var asd = ("asd","asd");
Is basically just syntactic sugar for
ValueTuple<string, string> valueTuple = new ValueTuple<string, string>("asd", "asd");
There isn't even anything overly magical about named tuples.
var asd = (bob1 : "asd", bob2 : "asd");
Console.WriteLine(asd.bob1);
Basically converts to the following
ValueTuple<string, string> valueTuple = new ValueTuple<string, string>("asd", "asd");
Console.WriteLine(valueTuple.Item1);
So you are essentially asking, why you can't use params
in a tuple initializer syntax.
Well, as discussed, because a value tuple initializer actually isn't a method, and as much as it looks like it, the arguments you give it are not a method parameters. Tuple syntax is it's own very special language feature. However, you do have options.
So let's look at what you are trying to achieve. If you had a method parameter as such
public void Test((string arg1, params string[] args) tuple)
the only advantage would be you could supply a comma separated list.
Test(("bob","args1","args2","args3"));
Since we can't, your options are
Test(("bob",new []{"args1","args2","args3"}));
Or with some tomfoolery you could use an explicit operator on your own struct.
public readonly struct Testing
{
public Testing(ITuple x)
{
CategoryName = (string) x[0];
Properties = EnumerateTuple<string>(x).ToArray();
}
public Testing(string categoryName,string[] properties)
{
CategoryName = categoryName;
Properties = properties;
}
private static IEnumerable<T> EnumerateTuple<T>(ITuple x)
{
for (var i = 1; i < x.Length; i++)
yield return (T) x[i];
}
public string CategoryName { get; }
public string[] Properties { get; }
public static implicit operator Testing((string, string[]) x) => new Testing(x.Item1,x.Item2);
public static implicit operator Testing(string x) => new Testing(x, Array.Empty<string>());
public static implicit operator Testing((string, string) x) => new Testing(x);
public static implicit operator Testing((string, string,string) x) => new Testing(x);
public static implicit operator Testing((string, string, string, string) x) => new Testing(x);
public static implicit operator Testing((string, string, string, string, string) x) => new Testing(x);
public static implicit operator Testing((string, string, string, string, string, string) x) => new Testing(x);
public static implicit operator Testing((string, string, string, string, string, string, string) x) => new Testing(x);
public static implicit operator Testing((string, string, string, string, string, string, string, string) x) => new Testing(x);
public static implicit operator Testing((string, string, string, string, string, string, string, string, string) x) => new Testing(x);
public static implicit operator Testing((string, string, string, string, string, string, string, string, string, string) x) => new Testing(x);
public static implicit operator Testing((string, string, string, string, string, string, string, string, string, string, string) x) => new Testing(x);
public static implicit operator Testing((string, string, string, string, string, string, string, string, string, string, string, string) x) => new Testing(x);
}
Which would allow shenanigan's such as this
public static void Test(Testing something)
{
Console.WriteLine(something.Category);
Console.WriteLine(string.Join(", ", something.Properties);
}
private static void Main(string[] args)
{
Test("asd");
Test(("asd"));
Test(("asd", "args1"));
Test(("asd", "args1", "args2"));
Test(("asd", new []{"args1", "args2"}));
}
Note : This was only for academic purposes, I really wouldn't expect anyone to want to do this