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

Kru*_*lur 44 .net c# expression-trees

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

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

this.Bottom == base.lineView.Top
Run Code Online (Sandbox Code Playgroud)

编译器给了我一个错误

表达式树可能不包含基本访问权限

所以我只是把它改成了

this.Bottom == this.lineView.Top
Run Code Online (Sandbox Code Playgroud)

因为该成员无论如何都受到保护,现在它起作用了.

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

Jon*_*eet 43

查看System.Linq.Expressions.Expression文档,我认为没有表示"基本成员访问"的表达式类型.不要忘记,即使在你的情况下它意味着同样的this,在其他情况下它不会:

class Test
{
    void Foo()
    {
        Expression<Func<string>> baseString = () => base.ToString();
    }

    public override string ToString()
    {
        return "overridden value";
    }
}
Run Code Online (Sandbox Code Playgroud)

这表示对Object.ToString()(for this)的非虚拟调用.我无法看到它将如何在表达式树中表示,因此错误.

现在,这导致了一个显而易见的问题,即为什么在表达式树中没有非虚拟基本成员调用的表示 - 我担心我无法回答那个部分...虽然我可以看到,如果你可以构建这个表达式以编程方式,允许您从外部绕过正常的多态,而不是仅从类本身内部(这是正常情况).这可能是原因.(不可否认,有其他方法可以非虚拟地调用方法,但这是另一回事,我敢说有些情况下表达式树是"可信任的",但其他代码则不然.)

  • 嘿乔恩,你的推测是正确的.详情请见我的回答. (5认同)
  • @EricLippert:太棒了 - 得到确认总是好的:) (3认同)
  • @PiotrZierhoffer:这是一个问答网站.如果您有新问题,请发布新问题.这样(1)很多人会尝试回答它,(2)人们更有可能找到那个问题的答案. (2认同)

Eri*_*ert 40

乔恩的回答是正确的.我想跟进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();
  }
Run Code Online (Sandbox Code Playgroud)

如果没有进行安全检查,那么部分信任的代码就D无法调用B.Dangerous实例.DD.Dangerous

因此,CLR验证程序限制您从类层次结构外部对虚拟方法执行非虚拟调用(基本调用当然是非虚拟调用).事实上,它走得更远; 你甚至不能从嵌套在其中的类中执行它D!(当然,如果您的程序被授予跳过验证的权限,那么您可以做任何您想做的事情;您可以在无法验证的代码中取消引用任意指向内存的指针,这比在虚拟方法上进行静态调用要糟糕得多.)

当我们设计表达式树时,我们不想处理这个混乱的安全问题.最简单的方法就是简单地使整件事变得非法.

表达式树存在许多其他安全问题,这些问题不容易解决,但这些问题是另一天的话题.

  • @NJones:我应该更清楚。CLR *验证程序* 通过无法验证调用的方法来限制您进行此类调用。如果您的程序被授予跳过验证权限,那么它可以这样做,因为验证程序一开始就不会运行。 (2认同)