在 C# 中使用子访问者
我正在设置一个测试组件并尝试保持其通用性。我想使用通用的 Visitor 类,但不确定是否使用后代类。
示例:
public interface Interface_Test_Case
{
void execute();
void accept(Interface_Test_Visitor v);
}
public interface Interface_Test_Visitor
{
void visit(Interface_Test_Case tc);
}
public interface Interface_Read_Test_Case
: Interface_Test_Case
{
uint read_value();
}
public class USB_Read_Test
: Interface_Read_Test_Case
{
void execute()
{ Console.WriteLine("Executing USB Read Test Case."); }
void accept(Interface_Test_Visitor v)
{ Console.WriteLine("Accepting visitor."); }
uint read_value()
{
Console.WriteLine("Reading value from USB");
return 0;
}
}
public class USB_Read_Visitor
: Interface_Test_Visitor
{
void visit(Interface_Test_Case tc)
{ Console.WriteLine("Not supported Test Case."); }
void visit(Interface_Read_Test_Case rtc)
{ Console.WriteLine("Not supported Read Test Case."); }
void visit(USB_Read_Test urt)
{ Console.WriteLine("Yay, visiting USB Read Test case."); }
}
// Code fragment
USB_Read_Test test_case;
USB_Read_Visitor visitor;
test_case.accept(visitor);
C# 编译器使用什么规则来确定代码片段将执行 USB_Read_Visitor
中的哪些方法?
我正在尝试排除我的测试组件的依赖关系。不幸的是,我当前的 Visitor 类包含与测试组件无关的类的 visit
方法。我是否正在努力实现不可能的目标?
I am setting up a testing component and trying to keep it generic. I want to use a generic Visitor class, but not sure about using descendant classes.
Example:
public interface Interface_Test_Case
{
void execute();
void accept(Interface_Test_Visitor v);
}
public interface Interface_Test_Visitor
{
void visit(Interface_Test_Case tc);
}
public interface Interface_Read_Test_Case
: Interface_Test_Case
{
uint read_value();
}
public class USB_Read_Test
: Interface_Read_Test_Case
{
void execute()
{ Console.WriteLine("Executing USB Read Test Case."); }
void accept(Interface_Test_Visitor v)
{ Console.WriteLine("Accepting visitor."); }
uint read_value()
{
Console.WriteLine("Reading value from USB");
return 0;
}
}
public class USB_Read_Visitor
: Interface_Test_Visitor
{
void visit(Interface_Test_Case tc)
{ Console.WriteLine("Not supported Test Case."); }
void visit(Interface_Read_Test_Case rtc)
{ Console.WriteLine("Not supported Read Test Case."); }
void visit(USB_Read_Test urt)
{ Console.WriteLine("Yay, visiting USB Read Test case."); }
}
// Code fragment
USB_Read_Test test_case;
USB_Read_Visitor visitor;
test_case.accept(visitor);
What are the rules the C# compiler uses to determine which of the methods in USB_Read_Visitor
will be executed by the code fragment?
I'm trying to factor out dependencies of my testing component. Unfortunately, my current Visitor class contains visit
methods for classes not related to the testing component. Am I trying to achieve the impossible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
由于您的
accept()
方法实际上并未调用任何visit()
方法,因此没有。 :)但是,如果您将其调用为:
编译器将看到
this
首先作为USB_Read_Test
的实例,然后是Interface_Read_Test_Case
,然后是Interface_Test_Case
。它将首先选择最直接的重载(或者可以使用隐式转换的重载),然后沿着继承链向下查找,直到找到适合重载的合适类型。因此在这种情况下,它将调用visit(USB_Read_Test)
。您可以通过强制转换来覆盖此行为:但是,如果您的类实现了多个接口,其中每个接口都有一个重载,但该类没有重载,您将收到必须解决的歧义错误。
例如,
有关详细信息,请参阅方法解析顺序和稍微相关的C#:将 null 传递给重载方法 - 调用哪个方法? 。
Since your
accept()
method doesn't actually call any of thevisit()
methods, none. :)However if you invoked it as:
the compiler will see that
this
is first as an instance ofUSB_Read_Test
, thenInterface_Read_Test_Case
, thenInterface_Test_Case
. It will choose the most direct overload first (or one where implicit conversions can be used) then go down the inheritance chain until it finds a suitable type that fits an overload. So in this case, it will callvisit(USB_Read_Test)
. You can override this behavior by casting:If however your class implements multiple interfaces, where each interface has an overload but there is none for the class, you will get ambiguity errors which you will have to resolve.
e.g.,
For more information, see Method resolution order and slightly related C#: Passing null to overloaded method - which method is called?.
不要为访问定义整个接口和关联的实现,而是定义一个接受 Action(或 Predicate,或 Func,具体取决于您希望访问者执行的操作)的 Visit 方法。
尽管我并不完全清楚您要做什么,但定义一个采用 Function 的方法可以消除定义所有这些接口的必要性。
Instead of defining an entire interface and associated implementations for Visiting, define a Visit method that accepts an Action (or Predicate, or Func depending on what you want the Visitor to do).
Though I'm not entirely clear on what you're trying to do, defining a method that takes a Function can remove the necessity of defining all those interfaces.
正如评论所说,接受不会调用任何访问方法,所以我根据我认为你的意思回答......
我本以为它是基于作为参数传入的对象的声明类型?
使用这两个参数进行调用应导致 obj1 的
visit(USB_Read_Test urt)
和 obj2 的visit(Interface_Read_Test_Case rtc)
。As the comment says, accept doesnt invoke any visit methods, so I answer based on what i think you meant...
I would have thought it based on the declared type of the object passed in as a parameter?
invoking with both as parameters should result in
visit(USB_Read_Test urt)
for obj1, andvisit(Interface_Read_Test_Case rtc)
for obj2.