create c# .net expression-trees

create - lambda c#



Error en C#: "un árbol de expresiones puede no contener un acceso base", ¿por qué no? (2)

Estaba llamando a un método que acepta Expression<Func<bool>> .

Como parte de la expresión que estaba pasando:

this.Bottom == base.lineView.Top

El compilador me dio un error que

un árbol de expresiones puede no contener un acceso base

Así que simplemente lo cambié a

this.Bottom == this.lineView.Top

porque el miembro estaba protegido de todos modos y ahora funciona.

Pero este error realmente me atrapó: ¿por qué demonios sería esta base un problema? Especialmente si usar this cambio funcionará pero sintácticamente será el mismo resultado (se accede a la misma variable)?


La respuesta de Jon es correcta. Quiero seguir el comentario de Jon:

Puedo ver que si pudieras construir esa expresión programáticamente, eso te permitiría eludir el polimorfismo normal desde el exterior en lugar de solo desde dentro de la clase (que es el caso normal). Esa puede ser la razón

Supongamos que tiene

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

No debería haber forma de que el código sea parcialmente confiable con una D en la mano para llamar a B.Dangerous en la instancia de D sin realizar la verificación de seguridad en D.Dangerous .

Por lo tanto, el verificador de CLR le impide realizar una invocación no virtual (una invocación de base es, por supuesto, no virtual) en un método virtual desde fuera de la jerarquía de clases. De hecho, va aún más lejos; ¡ni siquiera puedes realizar eso desde una clase anidada dentro de D ! (Por supuesto, si se le concede a su programa el derecho de omitir la verificación, puede hacer lo que desee; puede desviar punteros arbitrarios a la memoria en un código no verificable que es mucho peor que realizar una llamada estática en un método virtual).

Cuando estábamos diseñando árboles de expresión, no queríamos lidiar con este desordenado problema de seguridad. Lo más fácil era simplemente hacer que todo fuera ilegal.

Hubo una serie de otros problemas de seguridad con los árboles de expresión que no podrían resolverse tan fácilmente, pero esos son un tema para otro día.


Mirando la documentación de System.Linq.Expressions.Expression , no creo que haya un tipo de expresión que represente "acceso de miembro base". No olvide que aunque en su caso significó lo mismo que this , en otros casos no:

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

Aquí eso representaría una llamada no virtual a Object.ToString() (para this ). No puedo ver cómo se representaría eso en un árbol de expresiones, de ahí el error.

Ahora eso nos lleva a la pregunta obvia de por qué no hay una representación de la invocación de miembros de base no virtuales en los árboles de expresiones. Me temo que no puedo responder esa parte ... aunque puedo ver que si puedes construir esa expresión programáticamente, que le permitiría eludir el polimorfismo normal desde el exterior en lugar de desde dentro de la clase (que es el caso normal). Esa puede ser la razón. (Es cierto que hay otras maneras de llamar a los métodos de forma no virtual, pero esa es una cuestión diferente, y me atrevo a decir que hay situaciones en las que los árboles de expresiones son "confiables" pero otros no).