Как я моделирую анонимные классы в C#

Я пишу небольшую библиотеку структур данных в C#, и я сталкиваюсь с архитектурной проблемой. По существу у меня есть класс, который реализует шаблон "посетитель", и существует много возможных реализаций посетителей:

public interface ITreeVisitor
{
    U Visit(Nil s);
    U Visit(Node s);
}

public abstract class Tree : IEnumerable
{
    public readonly static Tree empty = new Nil();
    public abstract U Accept(ITreeVisitor visitor);
}

public sealed class Nil : Tree
{
    public override U Accept(ITreeVisitor visitor) { return visitor.Visit(this); }
}

public sealed class Node : Tree
{
    public Tree Left { get; set; }
    public T Value { get; set; }
    public Tree Right { get; set; }

    public override U Accept(ITreeVisitor visitor) { return visitor.Visit(this); }
}

Каждый раз, когда я хочу передать в посетителе, я должен создать класс посетителя, реализовать интерфейс и передать его в подобном это:

class InsertVisitor : ITreeVisitor> where T : IComparable
{
    public T v { get; set; };

    public Tree Visit(Nil s)
    {
        return new Node() { Left = Tree.empty, Value = v, Right = Tree.empty };
    }

    public Tree Visit(Node s)
    {
        switch (v.CompareTo(s.Value))
        {
            case -1: return new Node() { Left = Insert(v, s.Left), Value = s.Value, Right = s.Right };
            case 1: return new Node() { Left = s.Left, Value = s.Value, Right = Insert(v, s.Right) };
            default: return s;
        }
    }
}

public static Tree Insert(T value, Tree tree) where T : IComparable
{
    return tree.Accept>(new InsertVisitor() { v = value });
}

Мне не нравится писать так много шаблонного кода, потому что это становится очень грязным, когда у Вас есть нетривиальное количество реализаций посетителя.

Я хочу записать что-то подобное Java анонимных классов (код понятия):

public static Tree Insert(T v, Tree tree) where T : IComparable
{
    return tree.Accept>(new InsertVisitor()
        {
            public Tree Visit(Nil s) { return new Node() { Left = Tree.empty, Value = v, Right = Tree.empty }; }
            public Tree Visit(Node s)
            {
                switch (v.CompareTo(s.Value))
                {
                    case -1: return new Node() { Left = Insert(v, s.Left), Value = s.Value, Right = s.Right };
                    case 1: return new Node() { Left = s.Left, Value = s.Value, Right = Insert(v, s.Right) };
                    default: return s;
                 }
            }
        };
}

Там какой-либо путь состоит в том, чтобы моделировать анонимные классы с интерфейсными реализациями в C#?

10
задан Kevin Hakanson 2 August 2010 в 01:40
поделиться

1 ответ

Вы можете изменить «поведение» часть Класс от методов, определенных против интерфейса для делегатов, вызванных в соответствующем времени, и создать новый посетитель, передавая новые делегаты - тем самым зачисление анонимных функций для работы анонимных классов.

Эскиз кода (не тестировал, вы можете убрать при необходимости):

class CustomVisitor<T> : ITreeVisitor<T, Tree<T>> where T : IComparable<T>
{
    public T v { get; set; };
    public Func<Nil<T>,  Tree<T>> VisitNil  { get; set; }
    public Func<Node<T>, Tree<T>> VisitNode { get; set; }

    public Tree<T> Visit(Nil<T>  s) { return VisitNil(s);  }
    public Tree<T> Visit(Node<T> s) { return VisitNode(s); }
}

public static Tree<T> Insert<T>(T v, Tree<T> tree) where T : IComparable<T>
{
    return tree.Accept<Tree<T>>(new CustomVisitor<T> {
        VisitNil  = s =>
            return new Node<T>() { Left = Tree<T>.empty, Value = v, Right = Tree<T>.empty }; }
        VisitNode = s =>
        {
            switch (v.CompareTo(s.Value))
            {
                case -1: return new Node<T>() { Left = Insert(v, s.Left), Value = s.Value, Right = s.Right };
                case  1: return new Node<T>() { Left = s.Left, Value = s.Value, Right = Insert(v, s.Right) };
                default: return s;
             }
        }
    });
}
7
ответ дан 4 December 2019 в 02:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: