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# 中的错误:“表达式树可能不包含基本访问” - 为啥不呢?的主要内容,如果未能解决你的问题,请参考以下文章