class Foo { public static IEnumerable Range(int start, int end) { return Enumerable.Range(start, end); } public static void PrintRange(IEnumerable r) { foreach (var item in r) { Console.Write(" {0} ", item); } Console.WriteLine(); } } class Program { static void TestFoo() { Foo.PrintRange(Foo.Range(10, 20)); } static void Main() { TestFoo(); } }
Production attendue:
10 11 12 13 14 15 16 17 18 19 20
Sortie réelle:
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
Quel est le problème avec ce code? Que ce passe-t-il?
Le deuxième paramètre de Enumerable.Range
spécifie le nombre d’entiers à générer, pas le dernier entier de la plage.
Si nécessaire, il est assez facile de créer votre propre méthode ou de mettre à jour votre méthode Foo.Range
existante pour générer une plage à partir des parameters de start
et de end
.
Le second paramètre de Range
est le nombre d’éléments à produire.
Pourquoi n’est-ce pas la fin mais compte?
Comment énumérer une plage vide si vous avez des points de début et de fin? Par exemple, supposons que vous ayez un tampon de texte à l’écran et une sélection, et qu’il s’agisse d’un seul caractère commençant par le caractère 12 et se terminant par le caractère 12. Comment énumérer cette plage? Vous énumérez un caractère à partir du caractère 12.
Supposons maintenant que la sélection est zéro caractères. Comment l’énumérez-vous? Si vous avez début, taille, il vous suffit de passer à zéro pour la taille. Si vous avez début, fin, que faites-vous? Vous ne pouvez pas passer 12 et 12.
Maintenant, vous pouvez dire “bon, mais ne l’énumérez pas si c’est une plage vide”. Donc, vous finissez par prendre un code qui devrait ressembler à ceci:
var results = from index in Range(selectionStart, selectionSize) where blah blah blah select blah;
et au lieu d’écrire
IEnumerable results = null; if (selectionSize == 0) { results = Enumerable.Empty (); } else { results = from index in Range(selectionStart, selectionEnd) where blah blah blah select blah; }
ce qui me fait mal aux yeux.