1

Visitor パターンを使用しようとしていますが、次のようにしています。

public class EnumerableActions<T> : IEnumerableActions<T>
{
private IEnumerable<T> itemsToActOn;


public EnumerableActions ( IEnumerable<T> itemsToActOn )
{
  this.itemsToActOn = itemsToActOn;
}

public void VisitAllItemsUsing ( IVisitor<T> visitor )
{
  foreach (T t in itemsToActOn)
  {
    visitor.Visit ( t );// after this, the item is unaffected.
  }
}

訪問者 :

internal class TagMatchVisitor : IVisitor<Tag>
{
private readonly IList<Tag> _existingTags;

public TagMatchVisitor ( IList<Tag> existingTags )
{
  _existingTags = existingTags;
}

#region Implementation of IVisitor<Tag>

public void Visit ( Tag newItem )
{
  Tag foundTag = _existingTags.FirstOrDefault(tg => tg.TagName.Equals(newItem.TagName, StringComparison.OrdinalIgnoreCase));

  if (foundTag != null)
    newItem = foundTag; // replace the existing item with this one. 
}

#endregion
}

そして、私が訪問者を呼んでいるところ:

IList<Tag> tags = ..get the list;
tags.VisitAllItemsUsing(new TagMatchVisitor(existingTags));

だから..私はどこで参照を失っていますか? newItem = foundTag の後 - 訪問者の foreach で新しい値が得られることを期待しています - 明らかにそれは起こっていません。

編集私は答えを見つけたと思います-foreachでは変数は読み取り専用です。

http://discuss.joelonsoftware.com/default.asp?dotnet.12.521767.19

4

2 に答える 2

1

それが機能するには、まず「newItem」が「ref」である必要があります。次に、デリゲートの呼び出し後に更新された値で何かを行う必要があります (列挙子はコンテンツを更新する機能を提供しません)。しかし、コレクションへのほとんどの更新はとにかく列挙子を壊します!

それ以外の場合、置き換えた「newItem」はクライアントに表示されません。ただし、タグのプロパティへの変更(参照型で可変であると仮定) は行われます。

これが機能するには、itemsToActOn である必要がありIList<T>ます。次に、次を使用できます。

for(int i = 0 ; i < itemsToActOn.Count ; i++)
{
    T value = itemsToActOn[i];
    visitor.Visit(ref t)
    itemsToActOn[i] = value;
}

または、使用できる場合T Visit(T)

for(int i = 0 ; i < itemsToActOn.Count ; i++)
{
    itemsToActOn[i] = visitor.Visit(itemsToActOn[i]);
}
于 2008-11-12T08:52:10.490 に答える
0

はい、その通りですが、私はその場所で IEnumerable を使用しているため、実際には for を実行できません。

ただし、現在のリストに影響を与えるのではなく、新しいリストを返す方が正しいと思います。だから、Jean-Paul S. Boodhoo の ValueReturningVisitor を使用しています。

于 2008-11-12T09:02:52.450 に答える