c#中的错误:“表达式树可能不包含基访问”-为什么不呢?

本文关键字:访问 包含基 为什么不 错误 表达式 | 更新日期: 2023-09-27 17:49:15

我正在调用一个接受Expression<Func<bool>>的方法。

作为我传递的表达式的一部分:

this.Bottom == base.lineView.Top

编译器给了我一个错误

表达式树不能包含基访问

所以我把它改成

this.Bottom == this.lineView.Top

因为成员本来就被保护了,现在它可以工作了。

但是这个错误真的让我:为什么这个base会是一个问题?特别是如果使用this代替将工作,但语法上是相同的结果(相同的变量被访问)?

c#中的错误:“表达式树可能不包含基访问”-为什么不呢?

查看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内嵌套的类执行!(当然,如果你的程序被授予跳过验证的权利,那么你可以做任何你想做的;您可以在不可验证的代码中解引用任意指向内存的指针,这比在虚拟方法上进行静态调用要糟糕得多。

当我们设计表达式树时,我们不想处理这个混乱的安全问题。最简单的办法就是把整个事情定为非法。

表达式树还有其他一些不容易解决的安全问题,但这些是另一天的话题。

相关文章: