c#中的错误:“表达式树可能不包含基访问”-为什么不呢?
本文关键字:访问 包含基 为什么不 错误 表达式 | 更新日期: 2023-09-27 17:49:15
我正在调用一个接受Expression<Func<bool>>
的方法。
作为我传递的表达式的一部分:
this.Bottom == base.lineView.Top
编译器给了我一个错误
表达式树不能包含基访问
所以我把它改成
this.Bottom == this.lineView.Top
因为成员本来就被保护了,现在它可以工作了。
但是这个错误真的让我:为什么这个base
会是一个问题?特别是如果使用this
代替将工作,但语法上是相同的结果(相同的变量被访问)?
查看System.Linq.Expressions.Expression
文档,我认为没有表示"基本成员访问"的表达式类型。不要忘记,即使在你的情况下,它的意思和this
一样,在其他情况下,它不会:
class Test
{
void Foo()
{
Expression<Func<string>> baseString = () => base.ToString();
}
public override string ToString()
{
return "overridden value";
}
}
表示对Object.ToString()
的非虚调用(对于this
)。我不知道如何在表达式树中表示它,因此出现了错误。
现在这就引出了一个明显的问题为什么在表达式树中没有非虚基成员调用的表示-恐怕我不能回答这个部分…虽然我可以看到,如果您可以以编程方式构建该表达式,那将允许您从外部绕过正常的多态性,而不是仅从类本身内部(这是正常情况)。这可能就是原因。(诚然,还有其他非虚拟方式调用方法,但这是另一回事,我敢说有些情况下表达式树是"可信的",但其他代码不是。)
Jon的答案是正确的。我想跟进Jon的评论:
我可以看到,如果您可以通过编程方式构建该表达式,那将允许您从外部而不是仅从类本身内部绕过正常的多态性(这是正常情况)。这可能就是原因
假设你有
public abstract class B // Prevent instantiation
{
internal B() {} // Prevent subclassing outside the assembly.
public virtual void Dangerous() { ... }
}
public sealed class D : B
{
public override void Dangerous()
{
if (!Allowed()) throw whatever;
base.Dangerous();
}
对于拥有D
的部分可信代码,如果不进行D.Dangerous
中的安全检查,就不应该在D
的实例上调用B.Dangerous
。
CLR验证器因此限制您从类层次结构外部对虚方法执行非虚调用(基调用当然是非虚的)。事实上,它甚至更远;你甚至不能从D
内嵌套的类执行!(当然,如果你的程序被授予跳过验证的权利,那么你可以做任何你想做的;您可以在不可验证的代码中解引用任意指向内存的指针,这比在虚拟方法上进行静态调用要糟糕得多。
当我们设计表达式树时,我们不想处理这个混乱的安全问题。最简单的办法就是把整个事情定为非法。
表达式树还有其他一些不容易解决的安全问题,但这些是另一天的话题。