2010-03-18 5 views
4
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(); 
    } 
} 

Ожидаемый результат:перечислимых давая неожиданный выход

10 11 12 13 14 15 16 17 18 19 20 

Фактический выход:

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 

В чем проблема с этим кодом? Что происходит?

+0

Почему это не 'end', а' count'? Любые конкретные цели разработки lib devs? –

ответ

10

Второй параметр Enumerable.Range определяет количество целых чисел для генерации, не последнее целое число в диапазоне.

При необходимости достаточно просто создать собственный метод или обновить существующий метод Foo.Range, чтобы создать диапазон от start и end параметров.

+0

OMG его ужасно! –

+0

Не забывайте, что это указано в Enumerable not int, для большого количества (в большинстве?) Перечислений последнего элемента в диапазоне 'не будет иметь большого смысла. – FinnNk

+0

@FinnNk: вывод 'Enumerable.Range' всегда является' IEnumerable '. Если аргумент 'count' равен нулю, последовательность будет пуста, иначе она будет содержать последовательные целые числа. – LukeH

4

Второй параметр Range - это количество товаров для производства.

3

Почему это не конец, а счет?

Как вы можете перечислить пустой диапазон, если у вас есть начальная и конечная точки? Например, предположим, что у вас есть текстовый буфер на экране и выбор, а выбор имеет один символ, начинающийся с символа 12 и заканчивающийся символом 12. Как вы перечисляете этот диапазон? Вы перечисляете один символ, начинающийся с символа 12.

Теперь предположим, что выбор - это символы ZERO. Как вы это перечисляете? Если у вас есть начало, размер, вы просто передаете ноль для размера. Если у вас есть начало, конец, что вы делаете? Вы не можете пройти 12 и 12.

Теперь вы можете сказать «ну, просто не перечисляйте его, если его пустая область». Таким образом, вы в конечном итоге принимает код, который должен выглядеть следующим образом:

var results = from index in Range(selectionStart, selectionSize) 
       where blah blah blah 
       select blah; 

и вместо того, чтобы писать

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; 
} 

который причиняет боль мне глаза.

+1

Вы можете сделать окончание эксклюзивным и включать включительно, например count == end-start, что позволяет элегантно представлять пустые диапазоны. (Дейкстра согласился, см. EWD831). Но я очень рад, что так оно и есть, поэтому мне не нужно запоминать подробности об инклюзивных или эксклюзивных показателях. – Joren

+0

Joren: Хорошо, как вы представляете диапазон, который заканчивается на Int32.MaxValue, тогда? Если «конец» должен быть больше, чем последнее значение в последовательности, то у вас есть выбор. (1) не позволяют этому значению быть последним в последовательности, (2) делают конечную точку длинной, а не int только для этого случая. Оба кажутся плохим дизайном. –

+0

Но у вас все еще есть связанная с этим проблема: ваш диапазон не может распространяться от -1 до Int32.MaxValue, например, поскольку длина будет переполняться. С подходом Джорена вы могли бы поддерживать большее количество диапазонов, чем в текущем подходе. – kvb

Смежные вопросы