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

Posted

技术标签:

【中文标题】C# 中的错误:“表达式树可能不包含基本访问” - 为啥不呢?【英文标题】:Error in C#: "an expression tree may not contain a base access" - why not?C# 中的错误:“表达式树可能不包含基本访问” - 为什么不呢? 【发布时间】:2014-04-12 00:27:00 【问题描述】:

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

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

this.Bottom == base.lineView.Top

编译器给了我一个错误

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

所以我简单地把它改成了

this.Bottom == this.lineView.Top

因为无论如何该成员都受到了保护,现在它可以工作了。

但这个错误真的让我感到:为什么这个 base 会是个问题?特别是如果使用this 会起作用,但在语法上是相同的结果(访问相同的变量)?

【问题讨论】:

有趣的问题。但是,通常我从不无缘无故地使用base 关键字。也就是说,我仅在this 类型中的继承成员被具有相同名称的new 成员覆盖或隐藏时才使用它。也许出于这个原因,我从未在表达式树中遇到base 的这个问题。 【参考方案1】:

查看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)。我看不出这将如何在表达式树中表示,因此出现错误。

现在这就引出了一个明显的问题:为什么在表达式树中没有非虚拟基成员调用的表示 - 恐怕我无法回答那部分...... . 虽然我可以看到,如果您 可以 以编程方式构建该表达式,那将允许您从外部绕过正常的多态性 而不仅仅是从类本身内部(即正常情况)。这可能是原因。 (诚​​然,还有其他非虚拟调用方法的方式,但那是另一回事,我敢说在某些情况下表达式树是“受信任的”但其他代码不是。)

【讨论】:

嘿乔恩,你的猜想是正确的。详情见我的回答。 @EricLippert:太好了——得到确认总是好的 :) 完美的情况。有趣的问题有很好的答案,谢谢。我的后续问题。有没有non-reflection/non-reflection.emit其他方式绕过多态性? @PiotrZierhoffer:这是一个问答网站。如果您有新问题,请发布新问题。这样一来 (1) 很多人会尝试回答它,并且 (2) 搜索该问题答案的人更有可能找到它。 当然可以。但我只是期待一个“不”。 ;-)【参考方案2】:

乔恩的回答是正确的。我想跟进 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.Dangerous 中的安全检查,手头有D 的部分受信任代码应该无法在D 的实例上调用B.Dangerous

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

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

表达式树还有许多其他安全问题无法轻易解决,但这些是另一天的话题。

【讨论】:

我承认,在某些情况下,我通过反射调用了私人成员。事实上,这就是为什么我们被告知“私人”是为了保护您自己,即使它可以被同意的、清醒的成年人规避。但现在看来,在任何情况下都可能完全不可能调用被覆盖的成员。是这样吗? @NJones:我应该更清楚。 CLR verifier 通过调用验证方法失败来限制您进行此类调用。如果您的程序被授予跳过验证权限,那么它可以这样做,因为验证程序一开始就没有运行。

以上是关于C# 中的错误:“表达式树可能不包含基本访问” - 为啥不呢?的主要内容,如果未能解决你的问题,请参考以下文章

如何解决方法c#中的谓词错误

C# 错误中的左侧赋值

C#中的堆错误

如何处理c#中的错误代码

解决 C# 中的 Resharper 错误

C#:.NET 2.0 框架中的 Java 错误