29

C#を使用してアルゴリズム内でN回何かを行う必要があるたびに、このコードを記述します

for (int i = 0; i < N; i++)
{
    ...
}

Rubyを勉強して、このような同じセマンティクスで使用できるメソッドtimes()について学びました。

N.times do
    ...
end

C#のコードフラグメントはより複雑に見えるため、役に立たない変数iを宣言する必要があります。

IEnumerableを返す拡張メソッドを作成しようとしましたが、サイクル変数iを宣言する必要があるため、結果に満足できません。

public static class IntExtender
{
    public static IEnumerable Times(this int times)
    {
        for (int i = 0; i < times; i++)
            yield return true;
    }
}

...

foreach (var i in 5.Times())
{
    ...
}

いくつかの新しいC#3.0言語機能を使用して、N回のサイクルをよりエレガントにすることは可能ですか?

4

4 に答える 4

51

cvkの答えの少し短いバージョン:

public static class Extensions
{
    public static void Times(this int count, Action action)
    {
        for (int i=0; i < count; i++)
        {
             action();
        }
    }

    public static void Times(this int count, Action<int> action)
    {
        for (int i=0; i < count; i++)
        {
             action(i);
        }
    }
}

使用する:

5.Times(() => Console.WriteLine("Hi"));
5.Times(i => Console.WriteLine("Index: {0}", i));
于 2008-10-07T08:15:04.240 に答える
14

それは確かにC#3.0で可能です:

public interface ILoopIterator
{
    void Do(Action action);
    void Do(Action<int> action);
}

private class LoopIterator : ILoopIterator
{
    private readonly int _start, _end;

    public LoopIterator(int count)
    {
        _start = 0;
        _end = count - 1;
    }

    public LoopIterator(int start, int end)
    {
        _start = start;
        _end = end;
    }  

    public void Do(Action action)
    {
        for (int i = _start; i <= _end; i++)
        {
            action();
        }
    }

    public void Do(Action<int> action)
    {
        for (int i = _start; i <= _end; i++)
        {
            action(i);
        }
    }
}

public static ILoopIterator Times(this int count)
{
    return new LoopIterator(count);
}

使用法:

int sum = 0;
5.Times().Do( i => 
    sum += i
);

http://grabbagoft.blogspot.com/2007/10/ruby-style-loops-in-c-30.htmlから恥知らずに盗まれた

于 2008-10-07T08:09:51.923 に答える
0

.NET 3.5を使用している場合は、この記事で提案されているそれぞれの拡張メソッドを使用して、従来のループを回避することができます。

public static class IEnumerableExtensions
  {
      public static void Each<T>(
        this IEnumerable<T> source,
        Action<T> action)
      {
          foreach(T item in source)
          {
              action(item);
          }
      }
  }

この特定の拡張メソッドは、IEnumerableを実装するすべてのものにEachメソッドをスポット溶接します。このメソッドの最初のパラメーターは、これがメソッド本体内に何になるかを定義するため、これを知っています。アクションは事前定義されたクラスであり、基本的に値を返さない関数(デリゲート)の代わりになります。メソッド内では、要素がリストから抽出されます。このメソッドで可能になるのは、1行のコードで関数をきれいに適用できるようにすることです。

http://www.codeproject.com/KB/linq/linq-to-life.aspx

お役に立てれば。

于 2008-10-07T08:12:18.753 に答える
0

Times を Integer に追加する独自の拡張機能を作成しました (およびその他のもの)。ここでコードを取得できます: https://github.com/Razorclaw/Ext.NET

コードは、Jon Skeet の回答と非常によく似ています。

public static class IntegerExtension
{
    public static void Times(this int n, Action<int> action)
    {
        if (action == null) throw new ArgumentNullException("action");

        for (int i = 0; i < n; ++i)
        {
            action(i);
        }
    }
}
于 2013-04-12T15:59:44.407 に答える