From what I know, C# allows that only the last parameter of a method is of "variable length", for example:
T f(A a, params B[] b)
allows that if you have A r; .... B x, y, z; ....
you can call f like f (r, x, y, z)
. Why C# doesn't also define something like:
T f(params A[] a, params B[] b)
Because how would the compiler know when the variable arguments for the first parameter stop?
Pleas tell me what argOne
and argTwo
should contain inside of the method body:
void Foo( params object[] argOne, params object[] argTwo )
{
// whatever
}
Foo( 1, false, "Hello", new object(), 2.3 );
Because it would be too complicated to determine when such a construction is actually allowed.
(When the call would be unambiguous)
Although it would be possible to create a good set of rules, they would be rather complicated and difficult to understand. People would end up asking why case X doesn't work, if it has a subtle ambiguity.
For example:
object
or Enum
object
, Delegate
, nor MulticastDelegate
)sealed
or must be value types(some of these rules could be enforced at the callsite instead)
In practice, such a feature would have so many restrictions as to be almost worthless.
Therefore, this feature would start with -10,000 points.
It would also create a whole new category of breaking changes. Unsealing a type, adding implicit conversions, or other seemingly trivial things could now break client code.
Because of ambiguity. If you went and did:
T f(params int[] a, params int[] b)
And you called:
f(1, 2, 3, 4)
How would the compiler know where one started and the other began? You could argue that such cases could still be flagged as compilation errors and still allow the unambiguous cases to continue, but with inheritance it could get complicated and it just isn't worth it. Pass two arrays instead. I can't think of any situation that would merit two parameter arrays, and even then, it's syntactic sugar. There's no difference between it and just using arrays instead.
(Another example:
T f(params string[] a, params object[] b);
string
inherits from object
. This is still ambiguous...)
There are many edge cases that make this an improbable feature. Consider this example:
public static class Coolifier
{
public static void BeCool<A,B>(params A[] a, params B[] b)
{
}
}
Coolifier.BeCool<string,string> ("I", "don't", "work.", "DO", "I", "?");
The example shows how there is no way to know where the first params [] ends and the next begins.
It would pose question and lead to conflicts.
For example, let's say B
inherits from A
.
How would compiler understand:
f(A1, A2, B1, B2)
Would it mean f({A1, A2}, {B1, B2})
or f({A1, A2, B1}, {B2})
?
I think theoretically compiler could be smart and detect conflicts.
However, originally when .NET and C# itself were designed the idea was to try to avoid unambiguous and tricky cases like this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With