Disons que j'ai une classe comme ceci:
public class Fraction
{
int numerator;
int denominator;
public Fraction(int n, int d)
{
// set the member variables
}
// And then a bunch of other methods
}
Je veux initialiser un tableau d'une belle manière, et ce post est une grande liste de démarches qui sont sujettes à erreur ou syntaxiquement lourd.
Bien sûr, un constructeur tableau serait bien, mais il n'y a pas une telle chose:
public Fraction[](params int[] numbers)
Donc, je suis obligé d'utiliser une méthode comme
public static Fraction[] CreateArray(params int[] numbers)
{
// Make an array and pull pairs of numbers for constructor calls
}
ce qui est relativement maladroit, mais je ne vois pas un moyen de contourner cela.
Les deux formes sont sujettes à erreur, parce qu'un utilisateur pouvait à tort de passer un nombre impair d'éléments, peut-être parce qu'il a ignoré une valeur, ce qui risquerait de laisser la fonction de gratter sa tête en se demandant ce que l'utilisateur en fait voulu. Il peut lancer une exception, mais ensuite, l'utilisateur nécessité de try/catch. Je préfère ne pas l'imposer à l'utilisateur, si possible. Donc, nous allons appliquer les paires.
public static Fraction[] CreateArray(params int[2][] pairs)
Mais vous ne pouvez pas appeler cela CreateArray de bien belle façon, comme
Fraction.CreateArray({0,1}, {1,2}, {1,3}, {1,7}, {1,42});
Vous ne pouvez même pas faire
public static Fraction[] CreateArray(int[2][] pairs)
// Then later...
int[2][] = {{0,1}, {1,2}, {1,3}, {1,7}, {1,42}};
Fraction.CreateArray(numDenArray);
Notez que ce serait très bien fonctionner en C++ (je suis sûr).
Vous êtes forcé de faire l'une des opérations suivantes au lieu de cela, ce qui est abominable. La syntaxe est terrible et il semble vraiment bizarre d'utiliser un tableau en escalier lorsque tous les éléments ont la même longueur.
int[2][] fracArray = {new int[2]{0,1}, /*etc*/);
Fraction.CreateArray(fracArray);
// OR
Fraction.CreateArray(new int[2]{0,1}, /*etc*/);
De même, Python-style tuples sont illégales et la version C# est dégueulasse:
Fraction.CreateArray(new Tuple<int,int>(0,1), /*etc*/);
L'utilisation d'un pur tableau 2D pourrait prendre la forme suivante, mais il est illégal, et je suis sûr qu'il n'y a aucun moyen légal pour l'exprimer:
public static Fraction[] CreateArray(int[2,] twoByXArray)
// Then later...
Fraction[] fracArray =
Fraction.CreateArray(new int[2,4]{{0,1}, {1,2}, {1,3}, {1,6}});
Ce n'est pas le respect des paires:
public static Fraction[] CreateArray(int[,] twoByXArray)
OK, comment sur
public static Fraction[] CreateArray(int[] numerators, int[] denominators)
Mais alors les deux tableaux peuvent avoir des longueurs différentes. C++ permet
public static Fraction[] CreateArray<int N>(int[N] numerators, int[N] denominators)
mais bon, ce n'est pas le C++, est-il?
Ce genre de chose est illégal:
public static implicit operator Fraction[](params int[2][] pairs)
et impraticable de toute façon, à nouveau en raison de l'odieux de la syntaxe:
Fraction[] fracArray = new Fraction[](new int[2]{0,1}, /*etc*/ );
Ce pourrait être sympa:
public static implicit operator Fraction(string s)
{
// Parse the string into numerator and denominator with
// delimiter '/'
}
Ensuite, vous pouvez faire
string[] fracStrings = new string[] {"0/1", /*etc*/};
Fraction[] fracArray = new Fraction[fracStrings.Length];
int index = 0;
foreach (string fracString in fracStrings) {
fracArray[index] = fracStrings[index];
}
Je n'aime pas cette approche pour cinq raisons. L'un, de l'implicite cast inévitablement instancie un nouvel objet, mais nous avons déjà une très bonne, à savoir celui que nous essayons de les initialiser. De deux, il peut être difficile à lire. De trois, il vous oblige à faire explicitement ce que je voulais pour encapsuler dans la première place. Quatre, il laisse place à une mauvaise mise en forme. Cinq, il implique un temps d'analyse de littéraux de chaîne, qui ressemble plus à une blague qu'un bon style de programmation.
La suite nécessite également un gaspillage d'instanciation:
var fracArray = Array.ConvertAll(numDenArray, item => (Fraction)item);
La suite de l'utilisation d'un bien a le même problème, sauf si vous utilisez ces terribles les tableaux irréguliers:
public int[2] pair {
set {
numerator = value[0];
denominator = value[1];
}
}
// Then later...
var fracStrings = new int[2,4] {{0,1}, /*etc*/};
var fracArray = new Fraction[fracStrings.Length];
int index = 0;
foreach (int[2,] fracString in fracStrings) {
fracArray[index].pair = fracStrings[index];
}
Cette variation n'est pas le respect des paires:
foreach (int[,] fracString in fracStrings) {
fracArray[index].pair = fracStrings[index];
}
Encore une fois, cette approche est grand de toute façon.
Ce sont toutes les idées, je sais comment m'en tirer. Est-il une bonne solution?