Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在C中模拟匿名类#_C#_Design Patterns_Anonymous Class - Fatal编程技术网

C# 如何在C中模拟匿名类#

C# 如何在C中模拟匿名类#,c#,design-patterns,anonymous-class,C#,Design Patterns,Anonymous Class,我正在用C#编写一个小型数据结构库,我遇到了一个架构问题。本质上,我有一个实现访问者模式的类,访问者有很多可能的实现: public interface ITreeVisitor<T, U> { U Visit(Nil<T> s); U Visit(Node<T> s); } public abstract class Tree<T> : IEnumerable<T> { public readonly sta

我正在用C#编写一个小型数据结构库,我遇到了一个架构问题。本质上,我有一个实现访问者模式的类,访问者有很多可能的实现:

public interface ITreeVisitor<T, U>
{
    U Visit(Nil<T> s);
    U Visit(Node<T> s);
}

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

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

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

    public override U Accept<U>(ITreeVisitor<T, U> visitor) { return visitor.Visit(this); }
}
公共界面ITreeVisitor
{
U访问(无);;
U访问(节点s);
}
公共抽象类树:IEnumerable
{
public readonly static Tree empty=new Nil();
公开摘要(ITreeVisitor);
}
公众密封类别零:树
{
public override U Accept(ITreeVisitor){return visitor.Visit(this);}
}
公共密封类节点:树
{
左公共树{get;set;}
公共T值{get;set;}
公共树权限{get;set;}
public override U Accept(ITreeVisitor){return visitor.Visit(this);}
}
每当我想传入访问者时,我都必须创建一个访问者类,实现接口,并按如下方式传入它:

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

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

    public Tree<T> Visit(Node<T> 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;
        }
    }
}

public static Tree<T> Insert<T>(T value, Tree<T> tree) where T : IComparable<T>
{
    return tree.Accept<Tree<T>>(new InsertVisitor<T>() { v = value });
}
class InsertVisitor:ITreeVisitor其中T:IComparable
{
公共tv{get;set;};
公众树木参观(无)
{
返回新节点(){Left=Tree.empty,Value=v,Right=Tree.empty};
}
公共树访问(节点s)
{
开关(v.CompareTo(s.Value))
{
案例1:返回新节点(){Left=Insert(v,s.Left),Value=s.Value,Right=s.Right};
案例1:返回新节点(){Left=s.Left,Value=s.Value,Right=Insert(v,s.Right)};
默认值:返回s;
}
}
}
公共静态树插入(T值,树树),其中T:IComparable
{
返回tree.Accept(新的InsertVisitor(){v=value});
}
我不喜欢写那么多样板代码,因为当你有大量的访问者实现时,它会变得非常混乱

我想写一些类似于(概念代码)的东西:

publicstatictree插入(tv,Tree-Tree),其中T:IComparable
{
return tree.Accept(新的InsertVisitor())
{
公共树访问(nils){returnnewnode(){Left=Tree.empty,Value=v,Right=Tree.empty};}
公共树访问(节点s)
{
开关(v.CompareTo(s.Value))
{
案例1:返回新节点(){Left=Insert(v,s.Left),Value=s.Value,Right=s.Right};
案例1:返回新节点(){Left=s.Left,Value=s.Value,Right=Insert(v,s.Right)};
默认值:返回s;
}
}
};
}
有没有办法用C#中的接口实现来模拟匿名类?

您可以更改“行为”类的一部分来自根据接口定义的方法,在适当的时间调用委托,并通过传递新委托创建新的访问者——从而使匿名函数参与匿名类的工作

草图代码(未测试,您可以根据需要进行清理):

class CustomVisitor:ITreeVisitor其中T:IComparable
{
公共tv{get;set;};
公共函数VisitNil{get;set;}
公共函数访问节点{get;set;}
公众树木参观(无){回访}
公共树访问(节点){return VisitNode(s);}
}
公共静态树插入(T v,树树),其中T:IComparable
{
返回树。接受(新CustomVisitor){
VisitNil=s=>
返回新节点(){Left=Tree.empty,Value=v,Right=Tree.empty};}
VisitNode=s=>
{
开关(v.CompareTo(s.Value))
{
案例1:返回新节点(){Left=Insert(v,s.Left),Value=s.Value,Right=s.Right};
案例1:返回新节点(){Left=s.Left,Value=s.Value,Right=Insert(v,s.Right)};
默认值:返回s;
}
}
});
}

可能想解释什么是匿名接口。恐怕我不知道它是什么意思。@Noldorin:匿名接口不是最好的选择,我的意思是匿名类。Java有一个功能,你可以在不需要命名类的情况下动态实现接口——我想在C#中做类似的事情。你确定吗你不能处理委托?在C#中,匿名类型不能实现接口。请参阅此处了解更多信息:我不确定我是否正确,但你能用公共逻辑创建一个访问者基类而不是访问者接口吗?+1,+回答:哦,哇,这比我想象的要简单:)我担心需要使用
if(tree为Nil){…}else{…}
重新编写代码,以保持同一方法中包含的所有树遍历逻辑。非常感谢!这是函数式编程概念如何为面向对象语言增值的一个很好的例子
public static Tree<T> Insert<T>(T v, Tree<T> tree) where T : IComparable<T>
{
    return tree.Accept<Tree<T>>(new InsertVisitor<T>()
        {
            public Tree<T> Visit(Nil<T> s) { return new Node<T>() { Left = Tree<T>.empty, Value = v, Right = Tree<T>.empty }; }
            public Tree<T> Visit(Node<T> 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;
                 }
            }
        };
}
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;
             }
        }
    });
}