Есть ли метод "upto" в С#?
Здесь немного кода, который выводит квадраты чисел от 0 до 9:
for (int i = 0; i < 10; i++)
Console.WriteLine(i*i);
Выполнение чего-то от 0 до N на 1 через цикл for
- очень распространенная идиома.
Здесь используется метод UpTo
, который выражает это:
class MathUtil
{
public static void UpTo(int n, Action<int> proc)
{
for (int i = 0; i < n; i++)
proc(i);
}
}
Пример квадратов выше:
MathUtil.UpTo(10, (i) => Console.WriteLine(i * i));
Мой вопрос в том, имеет ли стандартная библиотека С# что-то вроде выше UpTo
?
В идеале, мне бы хотелось, чтобы метод "UpTo" был методом для всех целых объектов. Поэтому я мог бы сделать:
var n = 10;
n.UpTo(...);
Возможно ли это в С#?
Ответы
Ответ 1
Поверните его в метод расширения (обратите внимание на этот перед параметром n
, который определяет тип этот метод работает):
static class MathUtil
{
public static void UpTo(this int n, Action<int> proc)
{
for (int i = 0; i < n; i++)
proc(i);
}
}
Использование:
10.UpTo((i) => Console.WriteLine(i * i));
Примечание. Вышеупомянутый вызов метода не является особенно интуитивным. Помните, что код записывается один раз и читается много раз.
Возможно, что-то вроде ниже может быть немного лучше, но, честно говоря, я все равно просто напишу цикл foreach
.
0.UpTo(10 /*or 9 maybe*/, (i) => Console.WriteLine(i * i));
Если вы этого хотели, тогда вы можете написать метод расширения следующим образом:
public static void UpTo(this int start, int end, Action<int> proc)
{
for (int i = start; i < end; i++)
proc(i);
}
Измените <
на <=
, если вы хотите включить верхнюю границу.
Ответ 2
Посмотрите на LINQ TakeWhile или на свой конкретный случай целых чисел, используйте Enumerable.Range
Enumerable.Range(1, 10).Select(i => ...);
Возможно, вы не должны помещать действие в конец там, см. комментарии к ForEach здесь.
Ответ 3
Попробуйте следующее:
public static class IntExtensions
{
public static void UpTo(this int n, Action<int> proc)
{
for (int i = 0; i < n; i++)
proc(i);
}
}
С этим вы можете написать
10.UpTo(i => Console.WriteLine(i * i));
Функция, которую я написал, называется методом расширения.
Во время разработки вы заметите, что это не родная функция, потому что у нее есть другой значок.
Методы Estension являются статическими методами или функциями, включенными в статический класс, и тип, над которым они работают, является первым параметром, на котором вы должны использовать ключевое слово this
.
В классе IntExtensions
вы можете написать все методы, которые вам нравятся; группировка их внутри одного и того же статического класса упрощает управление ими.
Ответ 4
Хотите сделать это в одной строке? вот оно:
Enumerable.Range(0, 9).Select(i => i * i).ToList().ForEach(j=>Console.WriteLine("%d",j));
Ответ 5
Попробуйте Enumerable.Range
, возможно, в комбинации с Take
или TakeWhile
:
IEnumerable<int> values = Enumerable.Range(0, 20)
.Take(10); // Not necessary in this example
foreach(var value in values)
{
Console.WriteLine(value);
}
// or ...
foreach(var i in Enumerable.Range(0, 10))
{
Console.WriteLine(i * i);
}
В List<T>
есть ForEach
, который можно использовать для получения более синтаксиса для того, что вы хотите, но я считаю его плохим. Он принимает чистый синтаксис query/filter/transform, который работает эффективно неизменно и вводит побочные эффекты.
Для вашего будущего развлечения вы можете проверить методы расширения, IEnumerable<T>
и yield return
. Множество функциональных возможностей генератора и интересный синтаксис становятся возможными, когда вы используете эти три вещи в сочетании. Хотя я бы сказал, что этот конкретный пример - не лучшее место для их использования, потому что полученный синтаксис становится беспорядком.
Ответ 6
Сделайте свой метод следующим образом в статическом классе "Расширения", например:
public static void UpTo(this int n, Action<int> proc)
{
for (var i = 0; i < n; i++)
proc(i);
}
И использование:
var n = 10;
n.UpTo(i => Console.WriteLine(i * i));
Надеюсь, это поможет!:)