c#-基于参数的不同功能覆盖';类型
我正在玩c#-基于参数的不同功能覆盖';类型,c#,inheritance,methods,overloading,C#,Inheritance,Methods,Overloading,我正在玩AST,我想实现一个类Visitor,它遍历我的树并返回一个值。 我尝试了这种方式,但我的代码无法编译: abstract class ASTVisitor<T> { public abstract T Visit(SumExpr e); public abstract T Visit(ProductExpr e); public abstract T Visit(ConstantExpr e); public abstract T Visit(SymbolE
AST
,我想实现一个类Visitor
,它遍历我的树并返回一个值。
我尝试了这种方式,但我的代码无法编译:
abstract class ASTVisitor<T> {
public abstract T Visit(SumExpr e);
public abstract T Visit(ProductExpr e);
public abstract T Visit(ConstantExpr e);
public abstract T Visit(SymbolExpr e);
}
class DerivateVisitor : ASTVisitor<ASTExpr> {
public override ASTExpr Visit(SumExpr e){
return new SumExpr(
Visit(e.A),
Visit(e.B));
}
public override ASTExpr Visit(ProductExpr e){
return new SumExpr(
new ProductExpr(Visit(e.A), e.B),
new ProductExpr(Visit(e.B), e.A));
}
public override ASTExpr Visit(ConstantExpr e){
return new ConstantExpr(0);
}
public override ASTExpr Visit(SymbolExpr e) {
return new ConstantExpr(1);
}
}
SumExpr
,ProductExpr
,ConstantExpr
,SymbolExpr
继承自ASTExpr
。
为什么这不起作用?我怎样才能得到这种行为
以下是编译错误:
exit status 1
main.cs(56,7): error CS1502: The best overloaded method match for `ASTVisitor<ASTExpr>.Visit(SumExpr)' has some invalid arguments
main.cs(45,21): (Location of the symbol related to previous error)
main.cs(56,13): error CS1503: Argument `#1' cannot convert `ASTExpr' expression to type `SumExpr'
main.cs(57,7): error CS1502: The best overloaded method match for `ASTVisitor<ASTExpr>.Visit(SumExpr)' has some invalid arguments
main.cs(45,21): (Location of the symbol related to previous error)
main.cs(57,15): error CS1503: Argument `#1' cannot convert `ASTExpr' expression to type `SumExpr'
main.cs(61,23): error CS1502: The best overloaded method match for `ASTVisitor<ASTExpr>.Visit(SumExpr)' has some invalid arguments
main.cs(45,21): (Location of the symbol related to previous error)
main.cs(61,31): error CS1503: Argument `#1' cannot convert `ASTExpr' expression to type `SumExpr'
main.cs(62,23): error CS1502: The best overloaded method match for `ASTVisitor<ASTExpr>.Visit(SumExpr)' has some invalid arguments
main.cs(45,21): (Location of the symbol related to previous error)
main.cs(62,31): error CS1503: Argument `#1' cannot convert `ASTExpr' expression to type `SumExpr'
Compilation failed: 8 error(s), 0 warnings
退出状态1
main.cs(56,7):错误CS1502:ASTVisitor.Visit(SumExpr)的最佳重载方法匹配具有一些无效参数
main.cs(45,21):(与先前错误相关的符号位置)
cs(56,13):错误CS1503:参数`#1'无法将`ASTExpr'表达式转换为`SumExpr'类型
main.cs(57,7):错误CS1502:'ASTVisitor.Visit(SumExpr)'的最佳重载方法匹配具有一些无效参数
main.cs(45,21):(与先前错误相关的符号位置)
cs(57,15):错误CS1503:参数`#1'无法将`ASTExpr'表达式转换为`SumExpr'类型
main.cs(61,23):错误CS1502:ASTVisitor.Visit(SumExpr)的最佳重载方法匹配具有一些无效参数
main.cs(45,21):(与先前错误相关的符号位置)
cs(61,31):错误CS1503:参数`#1'无法将`ASTExpr'表达式转换为`SumExpr'类型
main.cs(62,23):错误CS1502:ASTVisitor.Visit(SumExpr)的最佳重载方法匹配具有一些无效参数
main.cs(45,21):(与先前错误相关的符号位置)
cs(62,31):错误CS1503:参数`#1'无法将`ASTExpr'表达式转换为`SumExpr'类型
编译失败:8个错误,0个警告
提前感谢。在代码的这一部分中,您正在调用
ASTVisitor。请使用无效参数(e.A)访问它预期的位置(e)
Visit
方法需要以下对象之一(SumExpr、ProductExpr、ConstantExpr、SymbolExpr
)
您正在通过e.A
,即ASTExpr
public override ASTExpr Visit(SumExpr e){
return new SumExpr(
Visit(e.A), // You are passing ASTExpr where as SumExpr is expected
Visit(e.B)); // You are passing ASTExpr where as SumExpr is expected
}
这肯定会改变你的逻辑,你将不得不努力
希望这有帮助问题是
class SumExpr : ASTExpr
{
public ASTExpr A, B;
public SumExpr(ASTExpr a, ASTExpr b) =>
(A, B) = (a, b);
public override string ToString() => $"({A.ToString()}) + ({B.ToString()})";
}
及
e、 A是ASTExpr,但没有可以为ASTExpr调用的方法访问
对象类型是在编译期间而不是在运行时定义的
添加以下方法
public override ASTExpr Visit(ASTExpr e)
{
if (e as SumExpr != null)
return Visit(e as SumExpr);
if (e as ProductExpr != null)
return Visit(e as ProductExpr);
if (e as ConstantExpr != null)
return Visit(e as ConstantExpr);
if (e as SymbolExpr != null)
return Visit(e as SymbolExpr);
throw new ArgumentException();
}
我建议对@Sergey Prosin的回答稍加改进。使用作为
可以工作,但速度较慢,因为每次使用都会首先检查类型是否匹配。相反,您可以将作为
表达式结果分配给变量,然后使用它,或者使用新的is
模式匹配语法:
public override ASTExpr Visit(ASTExpr e)
{
if (e is SumExpr sum)
return Visit(sum);
if (e is ProductExpr product)
return Visit(product);
if (e is ConstantExpr constant)
return Visit(constant);
if (e is SymbolExpr symbol)
return Visit(symbol);
throw new ArgumentException();
}
或更冷,开关
模式匹配:
public override ASTExpr Visit(ASTExpr e)
{
switch (e)
{
case SumExpr sum:
return Visit(sum);
case ProductExpr product:
return Visit(product);
case ConstantExpr constant:
return Visit(constant);
case SymbolExpr symbol:
return Visit(symbol);
default:
throw new ArgumentException();
}
}
你能提供更多细节吗?您遇到了什么类型的编译错误我添加了错误请在尝试编译代码时在Visual Studio中包含错误列表中的消息。请提供ASTExpr和SUMEPR定义。它们是如何连接的?是否还需要实现SUMEPR、ProductExpr、ConstantExpr、SymbolExpr和ASTExpr类?但是如果我为ASTExpr
添加覆盖,所有访问调用都将引用该覆盖。完全正确?不,编译器应该找到最合适的方法。您可以通过单击VSF中的GotoDefinition上下文菜单项进行检查,您可以将其作为visitor实现的示例,并从中获取实现详细信息。提供的代码看起来更简单,因此使用不同名称的Visit方法对meI来说更透明,因为meI只是对参数进行了更改。将更新我的代码:)
public override ASTExpr Visit(ASTExpr e)
{
if (e is SumExpr sum)
return Visit(sum);
if (e is ProductExpr product)
return Visit(product);
if (e is ConstantExpr constant)
return Visit(constant);
if (e is SymbolExpr symbol)
return Visit(symbol);
throw new ArgumentException();
}
public override ASTExpr Visit(ASTExpr e)
{
switch (e)
{
case SumExpr sum:
return Visit(sum);
case ProductExpr product:
return Visit(product);
case ConstantExpr constant:
return Visit(constant);
case SymbolExpr symbol:
return Visit(symbol);
default:
throw new ArgumentException();
}
}