Enumerável dando saída inesperada
-
20-09-2019 - |
Pergunta
class Foo
{
public static IEnumerable<int> Range(int start, int end)
{
return Enumerable.Range(start, end);
}
public static void PrintRange(IEnumerable<int> 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();
}
}
Saída esperada:
10 11 12 13 14 15 16 17 18 19 20
Saída real:
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
Qual é o problema com este código? O que está acontecendo?
Solução
O segundo parâmetro de Enumerable.Range
especifica o número de números inteiros para gerar, não o último número inteiro do intervalo.
Se necessário, é fácil o suficiente construir seu próprio método ou atualizar seu existente Foo.Range
método, para gerar um intervalo de start
e end
parâmetros.
Outras dicas
Segundo parâmetro de Range
é o número de itens a serem produzidos.
Por que não é acabado, mas conta?
Como você enumora um alcance vazio se tiver pontos de partida e final? Por exemplo, suponha que você tenha um buffer de texto na tela e uma seleção, e a seleção é de um único caractere iniciando no caractere 12 e terminando no caractere 12. Como você enumora esse intervalo? Você enumera um personagem começando no personagem 12.
Agora, suponha que a seleção seja zero caracteres. Como você o enumora? Se você tiver iniciado, tamanho, basta passar zero para o tamanho. Se você começou, termina, o que você faz? Você não pode passar 12 e 12.
Agora você pode dizer "bem, apenas não o enumerará se for um alcance vazio". Então você acaba tomando código que deve ficar assim:
var results = from index in Range(selectionStart, selectionSize)
where blah blah blah
select blah;
e em vez disso, escrevendo
IEnumerable<Chicken> results = null;
if (selectionSize == 0)
{
results = Enumerable.Empty<Chicken>();
}
else
{
results = from index in Range(selectionStart, selectionEnd)
where blah blah blah
select blah;
}
o que machuca meus olhos.