質問

可変整数を渡す必要があるイテレータを作成しています。

public IEnumerable<T> Foo(ref int valueThatMeansSomething)
{
    // Stuff

    yield return ...;
}

これにより、「エラー 476 イテレータには ref または out パラメータを含めることはできません」というメッセージが表示されます。

私が必要とするのは、この整数値をイテレータ内で変更し、イテレータの呼び出し元が使用できるようにすることです。言い換えれば、何を呼び出しても Foo() 上記は、の最終値を知りたいです valueThatMeansSomething そして Foo() それ自体を使用するかもしれません。実際には、値型ではなく参照型の整数が必要です。

私が考えられる唯一のことは、整数をカプセル化し、それを変更できるようにするクラスを作成することです。

public class ValueWrapper<T>
    where T : struct
{
    public ValueWrapper(T item)
    {
        this.Item = item;
    }

    public T Item { get; set; }
}

それで:

ValueWrapper<int> w = new ValueWrapper<int>(0);
foreach(T item in Foo(w))
{
    // Do stuff
}

if (w.Item < 0) { /* Do stuff */ }

これを処理するクラスまたはメカニズムはすでに BCL にありますか? あらゆる欠陥 ValueWrapper<T> 上記で提案されましたか?

(実際の使用方法は上記の例よりも複雑なので、内部で変数を処理します。 foreach を呼び出すループ Foo() はオプションではありません。期間。)

役に立ちましたか?

解決

いいえ、BCL にはこれを実行できるものは何も存在しないと確信しています。あなたの最善の選択肢は、まさにあなたが提案したものだと思います。の実装 ValueWrapper あなたが提案したものよりも実際には複雑である必要はありません。

もちろん、スレッドセーフであることが保証されているわけではありませんが、必要な場合は、自動プロパティをバッキング変数を含む標準プロパティに変換し、フィールドを次のようにマークするだけです。 volatile (値が常に最新であることを保証するため)。

他のヒント

あなただけの値を記述する必要がある場合は、別の手法は以下のようになります:

public IEnumerable<whatever> Foo(Action<int> setter) { ... }

int value = 0;
foreach(var x in Foo(x => {value=x;}) { ... }

偶然、私は7月に私のブログでの反復子ブロックのように多くの間抜けな制約がある理由のシリーズをやっているでしょう。 「なぜなしREFパラメータ?」初期のシリーズになります。

http://blogs.msdn.com/ericlippert/archive /tags/Iterators/default.aspxする

私は長いBCLは本当に、次のようなクラスやインタフェース何かを持っているべきであると考えています:

public delegate void ActByRef<T1,T2>(ref T1 p1);
public delegate void ActByRefRef<T1,T2>(ref T1 p1, ref T2 p2);
public interface IReadWriteActUpon<T>
{
  T Value {get; set;}
  void ActUpon(ActByRef<T> proc);
  void ActUpon<TExtraParam>(ActByRefRef<T, TExtraParam> proc, 
                           ref TExtraparam ExtraParam);
}

public sealed class MutableWrapper<T> : IReadWrite<T>
{
  public T Value;
  public MutableWrapper(T value) { this.Value = value; }
  T IReadWriteActUpon<T>.Value {get {return this.Value;} set {this.Value = value;} }
  public void ActUpon(ActByRef<T> proc)
  {
    proc(ref Value);
  }
  public void ActUpon<TExtraParam>(ActByRefRef<T, TExtraParam> proc, 
                           ref TExtraparam ExtraParam)
  {
    proc(ref Value, ref ExtraParam);
  }
}
多くの人々は本能的に自動プロパティのフィールドをラップしますが、

、フィールドには、多くの場合、値の型を使用する場合は特に、よりクリーンで効率的なコードを許します。多くの状況では、一方のプロパティを使用することによって得ることができる増加カプセル化は、効率的でコスト及びセマンティクス価値があるかもしれないが、タイプの全体の目的は、その状態が完全に露出し、可変されたクラスのオブジェクトであることがある場合、そのようなカプセル化は逆効果です。

インタフェースはMutableWrapper<T>代わりにインターフェイスを使用したいと思うのではなくIReadWriteActUpon<T>、さまざまな状況で有用である可能性のカプセル化を伴うだろうそのうちのいくつかは、誰かが誰ための多くのユーザーではないために含まれています<=> <=>インタフェースにカプセル化されたデータを使用するように設計されたコードに渡すことを望むかもしれないのインスタンスを有する。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top