我正在調用一個接受Expression<Func<bool>>
。
作為我傳遞的表達的一部分:
this.Bottom == base.lineView.Top
編譯器給了我一個錯誤
表達式樹可能不包含基本訪問權限
所以我只是把它改成了
this.Bottom == this.lineView.Top
因為該成員無論如何都受到保護,現在它起作用了。
但這個錯誤真的讓我:為什麼這個base
會成為一個問題?特別是如果使用this
可以工作但在語法上是相同的結果(相同的變量被訪問)?
查看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
)。我看不出它將如何在表達式樹中表示,因此錯誤。
現在,這引出了一個顯而易見的問題,即為什麼在表達式樹中沒有非虛擬基本成員調用的表示 - 我擔心我無法回答那個部分......雖然我可以看到,如果你可以構建這個表達式以編程方式,允許您從外部繞過正常的多態,而不是僅從類本身內部(這是正常情況)。這可能是原因。 (不可否認,有其他方法可以非虛擬地調用方法,但這是另一回事,我敢說有些情況下表達式樹是“可信的”,但其他代碼則不然。)
喬恩的回答是正確的。我想跟進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.Dangerous
手持D
部分信任代碼就B.Dangerous
在D
的實例上調用D.Dangerous
。
因此,CLR驗證程序限制您從類層次結構外部對虛擬方法執行非虛擬調用(基本調用當然是非虛擬調用)。事實上,它走得更遠;你甚至不能從嵌套在D
的類中執行它! (當然,如果您的程序被授予跳過驗證的權限,那麼您可以執行任何您想要的操作;您可以在無法驗證的代碼中取消引用任意指向內存的指針,這比在虛擬方法上進行靜態調用要糟糕得多。)
當我們設計表達式樹時,我們不想處理這個混亂的安全問題。最簡單的方法就是簡單地使整件事變得非法。
表達樹存在許多其他安全問題,這些問題無法輕易解決,但這些問題是另一天的話題。