我在哪里丢失参考?

时间:2008-11-12 08:43:51

标签: c# design-patterns 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中变量是readonly。

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

2 个答案:

答案 0 :(得分: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]);
}

答案 1 :(得分:0)

是的,你是对的 - 但我在那个地方使用IEnumerable,所以不能真正做到这一点。

但是我想回到新列表而不是影响当前列表更正确。所以我正在使用来自Jean-Paul S. Boodhoo的ValueReturningVisitor(灵感来自?:)。