Imagine que tu as ça quelque part
public static T AnyOne<T>(this T[] ra) where T:class
{
int k = ra.Length;
int r = Random.Range(0,k);
return ra[r];
}
ou même juste ça
public static string OneOf(this string[] strings)
{
return "a";
}
Alors, bien sûr, vous pouvez le faire ...
string[] st = {"a","b","c"};
string letter = st.AnyOne();
... qui est genial. MAIS. Il semblerait que vous ne puissiez PAS faire cela:
string letter = {"a","b","c"}.AnyOne();
ou bien peut-être ceci
string letter = ( {"a","b","c"} ).AnyOne();
ou quoi que ce soit d'autre que j'ai essayé.
En fait (1) pourquoi ne peut-on pas faire cela? et (2) est-ce que je manque quelque chose, comment feriez-vous cela s'il y a un moyen?
Réponses:
Vous devez d'abord créer le tableau, en utilisant
new[]
.Comme @hvd l'a mentionné, vous pouvez le faire sans paranthèses
(..)
, j'ai ajouté les paranthèses car je pense que c'est plus lisible.Et vous pouvez spécifier le type de données
new string[]
comme sur d'autres réponses a été mentionné.Vous ne pouvez pas simplement le faire
{"a","b","c"}
, car vous pouvez le considérer comme un moyen de peupler le tableau, pas de le créer.Une autre raison sera que le compilateur sera confus, ne saura pas quoi créer, par exemple, a
string[]{ .. }
ou aList<string>{ .. }
.En utilisant uniquement le
new[]
compilateur, vous pouvez savoir par type de données (".."
), entre{..}
, ce que vous voulez (string
). La partie essentielle est[]
que vous voulez un tableau.Vous ne pouvez même pas créer un tableau vide avec
new[]
.la source
string letter = new[] {"a","b","c"}.AnyOne();
est très bien. Si vous les voulez, si vous pensez que c'est plus lisible avec les parenthèses, elles sont valides, mais dans ce cas, je pense qu'il vaut au moins la peine de mentionner que c'est un choix conscient de votre part, qu'il n'a pas été forcé par la langue.Cette ligne:
est un raccourci pour une expression de création de tableau équivalente (sous ILSpy )
Cela
string[] st = {"a","b","c"}
ne peut être utilisé qu'au moment de la déclaration , vous ne pouvez pas ne pas l'utiliser ailleurs, vous ne pouvez même pas faire:Il est expliqué dans la section 7.6.10.4 pour l'expression Array Creation dans les spécifications du langage C #.
Donc cela
"{"a", "b", "c"}"
seul sans utilisation dans la déclaration ne signifie rien. Par conséquent, vous ne pouvez pas l'utiliser avec votre méthode d'extension, car votre méthode d'extension fonctionne sur un tableau.Déjà mentionné dans la réponse de @ adricadar , vous pouvez faire:
ou
la source
Je repousse les questions "pourquoi pas" car d'abord, les réponses ne sont presque jamais satisfaisantes - vous avez déjà obtenu la réponse "la fonctionnalité n'est pas comme vous le souhaitez car la spécification ne dit pas ce que vous voulez qu'elle dise" , ce qui, je suppose, n'était pas une réponse particulièrement satisfaisante. Deuxièmement, l'équipe de conception n'a pas à justifier pourquoi le monde n'est pas comme vous le souhaitez; les fonctionnalités n'existent pas gratuitement et sont ensuite conçues hors du langage; au contraire, les fonctionnalités doivent d'abord être justifiées, puis conçues dans.
Alors essayons de rendre votre question «pourquoi pas» un peu plus claire. La caractéristique existante est "un initialiseur de tableau peut être utilisé (a) sur le côté droit des égaux dans une initialisation ou (b) à droite d'une construction d'objet de type tableau". La fonctionnalité proposée est: "un initialiseur de tableau peut également être utilisé comme expression". La question est "quelles critiques Eric ferait-il du long métrage proposé?"
La première critique que je ferais est que le type d’expression n’est pas clair. Dans un initialiseur de variable, vous avez le type de la variable et dans une expression de création d'objet, vous avez le type de l'objet; à partir des deux, nous pouvons déduire le type du tableau construit. Sans aucun indice, quel type devrions-nous en déduire?
Dans C # 1.0, lorsque cette fonctionnalité a été ajoutée, il y avait un grand total de zéro inférences de type effectuées dans le langage. Un principe de conception dans les premiers jours de C # était "pas de surprises", et que le compilateur n'était pas "trop intelligent". Si le développeur souhaite qu'une expression soit d'un type particulier, ce type doit être d'une certaine manière évident dans l'expression. Quand tu dis
il est assez clair quel type est prévu. De même
La fonctionnalité proposée viole ce principe. L'expression doit avoir un type, mais le type de l'argument est loin d'être clair
De plus: Supposons que nous ayons deux surcharges de
M
, dont l'une prend un tableau deAnimal
et l'autre qui prend un tableau deIPet
. Quelle surcharge deM
est applicable? L'une des conversions est-elle meilleure que l'autre? Les types d'éléments sontCat
etDog
; est-il logique de déduire un type qui n'y figure même pas? Ce sont toutes des questions qui doivent être examinées par l'équipe de conception, et ce sont des questions qui n'ont en aucun cas des réponses évidentes. La fonctionnalité proposée nous conduit dans des eaux profondes dans un délai assez court.Désormais, C # 3.0 résout ce problème car C # 3.0 a ajouté de nombreuses fonctionnalités dans lesquelles le compilateur déduit des types au nom du développeur. Les principes antérieurs sur «pas de surprises» et «règles simples» étaient en conflit avec d'autres principes de conception nécessaires pour faire fonctionner LINQ. La fonctionnalité que vous proposez devrait-elle avoir été ajoutée en C # 3.0?
Ça aurait pu. La fonctionnalité réellement ajoutée dans C # 3.0 était:
déduit le type du tableau à l'aide de l'algorithme: prenez les expressions pour les éléments qui ont des types, déterminez lequel de ces types est le type le plus général unique vers lequel toutes les autres expressions sont convertibles, et si un tel type existe, choisissez-le. Sinon, produire une erreur,
Cette fonctionnalité aurait pu être davantage assouplie pour rendre l'
new[]
option. Cela n'a pas été fait.Maintenant, si vous m'aviez demandé dans la période C # 3.0 de critiquer la fonctionnalité proposée, j'aurais fait remarquer que (1) le compilateur C # 3.0 risquait déjà de faire glisser le calendrier de la version entière, alors n'en ajoutons plus charge de conception, d'implémentation et de test pour une fonctionnalité totalement inutile qui évite à l'utilisateur six frappes, et (2) C # 3.0 a également ajouté des initialiseurs de collection:
pourquoi devrait
{10, 20, 30}
être automatiquement un tableau ? Pourquoi ne devrait-il pas être unList<int>
? Ou l'un des nombreux autres types? Pourquoi le biais vers les tableaux? N'oubliez pas qu'une fois que nous avons choisi de consacrer la syntaxe des tableaux, nous y restons pour toujours . Ce n'est peut-être jamais autre chose, donc la fonctionnalité proposée n'est pas seulement inutile, elle empêche également d'éventuelles fonctionnalités futures qui semblent plausibles.En résumé: la fonctionnalité proposée violait directement certains des principes de conception de C # 1.0. Cela n'ajoute rien d'autre qu'une charge inutile à C # 3.0. Dans toutes les versions du langage depuis C # 3.0, la fonctionnalité proposée n'a aucun bon argument pour recommander d'y consacrer du temps, des efforts et de l'argent par rapport à de nombreuses autres fonctionnalités plus valables.
Par conséquent, aucune fonctionnalité de ce type.
la source