Дизайн метода – возвратить два значения
От: xy012111  
Дата: 11.12.15 18:20
Оценка:
Доброго!

Предположим, есть у меня есть такой вот визитор (c#):
class Xxx
{
  protected override TContext Accept<TContext>(Visitor<TContext> visitor, TContext context) {
    return visitor.VisitXxxValue(this, context);
  }
}

… abstract class Visitor<TContext>
{
  internal TContext VisitXxxValue(Xxx value, TContext context) {
    var visiting = OnXxxVisiting(value, context);
    var visit = VisitXxx(value, visiting);
    return OnXxxVisited(value, visit);
  }

  protected virtual TContext OnXxxVisiting(Xxx value, TContext context) {
    return OnBaseVisiting(value, context);
  }

  protected virtual TContext VisitXxx(Xxx value, TContext context) {
    // Посещение чилдов, эти внутренности совсем не важны
    return …;
  }

  protected virtual TContext OnXxxVisited(Xxx value, TContext context) {
    return OnBaseVisited(value, context);
  }
}


Я же хочу сделать так, что бы метод OnXxxVisiting возвращал бы помимо контекста ещё и bool — нужно ли вообще посещать элемент. (Это нужно для того, что бы переопределив OnBaseVisiting можно было бы отменить посещение вообще целой группы элементов, не переопределяя Visit для каждого)


Тут есть варианты:

  1.   protected virtual bool OnXxxVisiting(Xxx value, ref TContext context) {
        return OnBaseVisiting(value, ref context);
      }
    
      internal TContext VisitXxxValue(Xxx value, TContext context) {
        if(OnXxxVisiting(value, ref context)) {
          var visit = VisitXxx(value, start);
          return OnXxxVisited(value, visit);
        } else {
          return context;
        }
      }


  2.   protected virtual bool OnXxxVisiting(Xxx value, TContext context, out TContext result) {
        return OnBaseVisiting(value, context, out result);
      }
    
      internal TContext VisitXxxValue(Xxx value, TContext context) {
        TContext visiting;
        if(OnXxxVisiting(value, context, out visiting)) {
          var visit = VisitXxx(value, visiting);
          return OnXxxVisited(value, visit);
        } else {
          return visiting;
        }
      }


  3.   protected virtual TContext OnXxxVisiting(Xxx value, TContext context, out bool continueVisiting) {
        return OnBaseVisiting(value, context, out continueVisiting);
      }
    
      internal TContext VisitXxxValue(Xxx value, TContext context) {
        bool continueVisiting;
        var visiting = OnXxxVisiting(value, context, out continueVisiting);
        if(continueVisiting) {
          var visit = VisitXxx(value, visiting);
          return OnXxxVisited(value, visit);
        } else {
          return visiting;
        }
      }

Я бы сам остановился на третьем варианте, но смущает то, что имеется так же и Visitor без контекста, в котором OnXxxVisiting возвращает как раз bool
  protected virtual bool OnXxxVisiting(Xxx value) {
    return OnBaseVisiting(value);
  }

  internal void VisitXxxValue(Xxx value) {
    if(OnXxxVisiting(value)) {
      VisitXxx(value);
      OnXxxVisited(value);
    }
  }

и хочется однообразия в интерфейсах. Или и в бесконтекстом варианте сделать так:
  protected virtual void OnXxxVisiting(Xxx value, out bool continueVisiting) {
    OnBaseVisiting(value, out continueVisiting);
  }

  internal void VisitXxxValue(Xxx value) {
    bool continueVisiting;
    OnXxxVisiting(value, out continueVisiting);
    if(continueVisiting) {
      VisitXxx(value);
      OnXxxVisited(value);
    }
  }


Ваши варианты?

Сожержимое всех методов, которые тут показаны генерируется автоматически, поэтому объём кода внутри не так важен.
Отредактировано 11.12.2015 18:32 xy012111 . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.