Где я теряю ссылку? - PullRequest
       10

Где я теряю ссылку?

1 голос
/ 12 ноября 2008

Я пытаюсь использовать Шаблон посетителя, и у меня есть следующее:

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

Ответы [ 2 ]

1 голос
/ 12 ноября 2008

Чтобы это работало, сначала "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]);
}
0 голосов
/ 12 ноября 2008

Да, вы правы - но я использую IEnumerable в этом месте, так что не могу с этим справиться.

Однако, я думаю, правильнее будет вернуть новый список, а не влиять на текущий. Поэтому я использую ValueReturningVisitor - вдохновленный (взятый? :)) от Jean-Paul S. Boodhoo.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...