> . As part of the ex...">

Error in C #: "expression tree cannot contain basic access" - why not?

I called a method that accepts Expression<Func<bool>> .

As part of the expression I passed:

 this.Bottom == base.lineView.Top 

The compiler gave me an error that

expression tree cannot contain basic access

So I just changed it to

 this.Bottom == this.lineView.Top 

because the item was protected anyway, and now it works.

But this error really caused me: why was this base problem a problem? Especially if using this will work instead, but syntactically will be the same result (the same variable being accessed)?

+44
c # expression-trees
Mar 08 '14 at 19:40
source share
2 answers

In the System.Linq.Expressions.Expression documentation, I don't think there is a type of expression that represents "access to the base member". Do not forget that, although in your case it meant the same as just this , in other cases it would not be:

 class Test { void Foo() { Expression<Func<string>> baseString = () => base.ToString(); } public override string ToString() { return "overridden value"; } } 

Here it will represent a non-virtual call to Object.ToString() (for this ). I do not see how this will be represented in the expression tree, therefore, an error.

Now this leads to the obvious question of why there is no idea of ​​calling a non-virtual base element in expression trees - I'm afraid I can not answer this part ... although I see that if you can create this expression programmatically, that will allow you get around ordinary polymorphism from the outside, and not just inside the class itself (which is a normal case). This may be the reason. (Admittedly, there are other ways to call methods not virtually, but that’s another question, and I dare to say that there are situations where expression trees are “trusted” but no other code.)

+43
Mar 08 '14 at 19:55
source share

John's answer is correct. I want to follow John's comment:

I see that if you could programmatically create this expression, it would allow you to bypass the normal polymorphism from the outside, and not just inside the class itself (which is a normal case). This may be the reason.

Suppose you have

 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(); } 

You cannot use partially trusted code with D to call B.Dangerous on an instance of D without security checks in D.Dangerous .

Thus, the CLR verifier forbids you to make a non-virtual call (the base call, of course, is not virtual) by a virtual method from outside the class hierarchy. In fact, he goes even further; you can't even do this from a class nested in D ! (Of course, if your program is given the right to skip checking, then you can do whatever you want, you can dereference arbitrary pointers to memory in unchecked code, which is much worse than a static call to a virtual method.)

When we designed expression trees, we did not want to deal with this dirty security problem. The easiest way was to just make everything illegal.

Many other security issues have arisen with expression trees that could not be easily resolved, but this is a topic for another day.

+40
Mar 08 '14 at 20:12
source share



All Articles