Imagine you have this somewhere
public static T AnyOne(this T[] ra) where T:class
{
int k = ra.Length;
int r = Random.Range(0,k);
re
(1) why can one not do that?
{"a","b","c"}.AnyOne();
This line:
string[] st = {"a","b","c"};
is a short hand for an equivalent array creation expression (under ILSpy)
string[] st = new string[] {"a","b","c"};
This string[] st = {"a","b","c"}
can only be used at the time of declaration, you can't not use it elsewhere, you can't even do:
string[] st;
st = {"a", "b", "c"}; //Error
It is explained under Section 7.6.10.4 for Array Creation expression in C# language specifications.
So this "{"a", "b", "c"}"
alone without usage in declaration means nothing. Hence you can't use it with your extension method, as your extension method operates on an array.
(2) am I missing something, how would you do that if there is a way?
Already mentioned in @adricadar's answer, you can do:
(new[] {"a","b","c"}).AnyOne();
or
(new string[] {"a","b","c"}).AnyOne();
I push back on "why not" questions because first, the answers are almost never satisfying -- you've already gotten the answer "the feature is not the way you want it because the specification does not say what you want it to say", which I imagine was not a particularly satisfying answer. Second, the design team does not have to justify why the world is not the way you want it to be; features do not exist for free and are then designed out of the language; rather, features have to be first justified, and then designed in.
So let's try to make your "why not" question a little more crisp. The existing feature is "an array initializer may be used (a) on the right side of the equals in an initialization or (b) to the right of an object construction of array type." The proposed feature is: "an array initializer may also be used as an expression". The question is "what criticisms would Eric make of the proposed feature?"
The first criticism I would make is that it is unclear what the type of the expression is. In a variable initializer you have the type of the variable and in an object creation expression you have the type of the object; from both of these we can deduce the type of the constructed array. Without either hint, what type should we deduce?
In C# 1.0, when this feature was added, there were a grand total of zero type inferences made in the language. A design principle in the early days of C# was "no surprises", and that the compiler was not "too smart". If the developer intends an expression to be of a particular type then that type should be in some way obvious in the expression. When you say
new double[] { 1, 2, 3.4 }
it is pretty clear what type is intended. Similarly
new Animal[] { cat, dog, null }
The proposed feature violates this principle. The expression must have a type, but it is by no means clear what the type of the argument is in
M({cat, dog, null})
Moreover: Suppose we have two overloads of M
, one of which takes an array of Animal
and one which takes an array of IPet
. Which overload of M
is applicable? Is one of the conversions better than the other? The types of the elements are Cat
and Dog
; does it make sense to deduce a type that does not even appear there? These are all questions which must be considered by the design team, and these are questions which have by no means obvious answers. The proposed feature leads us into deep waters in quite short order.
Now, C# 3.0 solves this problem because C# 3.0 added numerous features where the compiler infers types on behalf of the developer. The earlier principles about "no surprises" and "simple rules" were in conflict with other design principles needed to make LINQ work. Should the feature you propose have been added in C# 3.0?
It could have been. The feature actually added in C# 3.0 was:
new[] { x, y, z }
infers the type of the array using the algorithm: take the expressions for elements that have types, determine which of those types is the unique most general type to which all the other expressions are convertible, and if such a type exists, choose that. Otherwise produce an error,
That feature could have been further relaxed to make the new[]
optional. This was not done.
Now, if you had asked me in the C# 3.0 timeframe to criticize the proposed feature I would have pointed out that (1) the C# 3.0 compiler was already in grave danger of slipping the schedule for the entire release, so let's not add any more design, implementation and testing burden for a thoroughly unnecessary feature that saves the user six keystrokes, and (2) C# 3.0 also added collection initializers:
new List<int>() { 10, 20, 30 }
why should {10, 20, 30}
automatically be an array? Why shouldn't it be a List<int>
? Or any one of a number of other types? Why the bias towards arrays? Remember, once we choose to enshrine the syntax for arrays, we are stuck with it forever. It may never be anything else, so the proposed feature is not only unnecessary, it also prevents possible future features that seem plausible.
Summing up: the proposed feature directly violated some of the design principles of C# 1.0. It adds nothing but unnecessary burden to C# 3.0. In all versions of the language since C# 3.0, the proposed feature has no good argument to recommend spending time, effort and money on it over many other more worthy features.
Therefore, no such feature.
You have to create the array first, using new[]
.
string letter = (new[] {"a","b","c"}).AnyOne();
As @hvd mentioned you can do this without parantheses (..)
, I added the parantheses because I think it's more readable.
string letter = new[] {"a","b","c"}.AnyOne();
And you can specify the data type new string[]
as on other answers has been mentioned.
You can't just do {"a","b","c"}
, because you can think of it as a way to populate the array, not to create it.
Another reason will be that the compiler will be confused, won't know what to create, for example, a string[]{ .. }
or a List<string>{ .. }
.
Using just new[]
compiler can know by data type (".."
), between {..}
, what you want (string
). The essential part is []
, that means you want an array.
You can't even create an empty array with new[]
.
string[] array = new []{ }; // Error: No best type found for implicity-typed array