0

(インデックスを介して)反復処理できないコレクションがありますが、実装していますIEnumerable

列挙するときにそのコレクション内のオブジェクトを置き換える方法はありますか? これがループでは不可能であることはわかっていforeachますが、やりたいと思うのは合理的なことのようです。

C# のポインターの使用を検討するところまで行きましたが、マネージド型では機能しません。

配列にすべてのデータを入力して、そのように編集できることは知っていますが、

  1. とても無駄に思えます
  2. さらに重要なことは、構造全体が失われることです。

例として:

public void Example(object a,object b, object c)
{
    object[] ex = {a,b,c};
    object d = new MyCustomType();
}

インデクサーを使用せずに、どうすればex保持でき{a,d,c}ますか? アクセスできる唯一の方法exは、列挙子を使用することだとします。Addこの型にはorAddAtメソッドはありません(ここでは によって再生されobject[]ます。基になる構造が不明/非常に複雑であると仮定します。

これどうやってするの?

4

4 に答える 4

1

パヨが言ったように、あなたの声明は互いに矛盾しています。IEnumerableを反復処理することはできませんが、反復であるforeachループにいます。そして、IEnumerableは、コレクションから列挙できると言っています。しかし、ここにあなたの質問に対する私の意見があります:

コレクションを介して列挙する場合、列挙しているデータを変更しようとする試みは制限されます。そして、あなたは間違いなく何も削除することはできません。一部には、これは列挙を変更する可能性があるためです。

考えられるアプローチは、アイテムのリストを作成し、リストを列挙して、必要なものをリストに入れることです。次に、.Add(IEnumerable list)が公開されていると想定して、IEnumerableをリロードします。

ある状況では、IEnumerableから削除したいアイテムがあったので、foreachを実行し、削除したい各オブジェクトを追跡し、列挙後に、保存した各オブジェクトの削除を実行しました。

現在、linqを使用すると、必要なものを明確に定義したクエリを表現して(不要なものを除外して)、IQueriable結果セットに対して処理できる場合は、オブジェクトを削除するなどの操作をより簡単に行うことができます。

于 2012-06-05T18:51:02.403 に答える
0

一言で言えば:リンクリスト

実装する必要があるかどうかIEnumerable(LINQで使用する場合など)、または参照する不思議なコレクションをどの程度制御できるかについては、まだ述べていません。しかし、あなたの質問が基本的に「C#で反復しながらある種のコレクションを変更するにはどうすればよいですか?」...まあ、これはリンクリストが実際に優れている(そして非常に効率的である)ものです。例えば:

var intList = new LinkedList<int>(new []{ 1, 4, 5, 7, 12 });
var node = intList.First;
do {
    // do stuff with node
    if (node.Value < 3){
        node.List.AddAfter(node, node.Value + 1);
    } else if(node.Value == 7) {
        var prevNode = node.Previous;
        node.List.Remove(node);
        node = prevNode;
    }

    // Get the next node
    node = node.Next;
} while (node != null);

私たちはあなたからの十分な情報を持っていないので、あなたがあなたのソース収集をリンクリストにコピーするべきだと言っているのではありません。しかし、おそらくこれは、リンクリストが何のためにあるのか、つまり、インデックスアクセサーなしで列挙しながら変更することをあなたと将来の読者に示すことができます。

また、参照するこのコレクションが完全に架空のものである場合、提供した情報には答えがないことに注意してくださいIEnumerable。「基になるコレクション」を変更するためのメソッドは必要ありません。実際、IEnumerable基礎となるコレクションが存在する必要はありません。たとえば、IEnumerable<int>基になるコレクションのないを返すメソッドは次のとおりです。

public static IEnumerable<int> Range(int minValue, int maxValue) {
    int current = minValue;
    while (current <= maxValue) {
        yield return current;
        current++;
    }
}
于 2012-06-05T19:15:40.113 に答える
0

あなたの説明では、簡単にアイテムを交換する方法は考えられません。
あなたはそれを主張します:

  • 追加/削除メソッドはありません - 簡単な変更方法はありません
  • 基礎となるコレクションの形式が不明です - リフレクション オプションが使いにくくなっています
  • 公開されているのは列挙子だけです。つまり、foreach しかできません。

考えられる解決策は次のとおりです。

  • 基礎となる型を反映し、その形式を学び、リフレクションによって必要なものを変更します
  • 可能であれば、すでに提案されているように、ディープ コピーを使用してください。ディープ コピーという用語に慣れていない場合は、置き換えたいオブジェクトとそのプロパティを必要なだけ深く、置き換えたいオブジェクトの並列値で再帰的に更新することを意味します。 . もちろん、各オブジェクトのデータ/値ではなく参照を気にする場合、このソリューションは機能しません。SO でディープ コピーを使用する方法を説明するスレッドが多数あるため、サンプルを見つけるのに問題はありません。
于 2012-06-05T19:19:15.697 に答える
0

元のコレクションにはどのような変異方法がありますか? アイテムの削除または交換をサポートしている場合、削除または交換するアイテムをどのような方法で識別しますか?

IEnumerable基になるコレクションが変更された場合でも、列挙を実装または許可する一部のクラスIEnumerable<T>(列挙全体でコレクション内にあるアイテムは正確に返され、列挙の一部のコレクション内にあるアイテムは最大でも返されます)列挙中にまったくコレクションではないものはまったく返されません)。使用しているクラスがそのように動作する場合は、すばらしいことです。

それ以外の場合は、おそらく、クラスを列挙している間に「編集」のリストを作成し、列挙が完了した後にそれらの編集を適用することをお勧めします。

于 2012-06-05T21:15:30.253 に答える