埃里克利珀特只是blogged on this very topic。
它的基本要点是确保一个类可以“信任”受保护方法的调用者。在这方面,共享一个公共基类的类(即使该公共基类定义了受保护的方法)本质上是陌生的。
埃里克的例子是基于银行申请的想法。而不是重建他的榜样,我就吐出在这里:
// Good.dll:
public abstract class BankAccount
{
abstract protected void DoTransfer(
BankAccount destinationAccount,
User authorizedUser,
decimal amount);
}
public abstract class SecureBankAccount : BankAccount
{
protected readonly int accountNumber;
public SecureBankAccount(int accountNumber)
{
this.accountNumber = accountNumber;
}
public void Transfer(
BankAccount destinationAccount,
User authorizedUser,
decimal amount)
{
if (!Authorized(user, accountNumber)) throw something;
this.DoTransfer(destinationAccount, user, amount);
}
}
public sealed class SwissBankAccount : SecureBankAccount
{
public SwissBankAccount(int accountNumber) : base(accountNumber) {}
override protected void DoTransfer(
BankAccount destinationAccount,
User authorizedUser,
decimal amount)
{
// Code to transfer money from a Swiss bank account here.
// This code can assume that authorizedUser is authorized.
// We are guaranteed this because SwissBankAccount is sealed, and
// all callers must go through public version of Transfer from base
// class SecureBankAccount.
}
}
// Evil.exe:
class HostileBankAccount : BankAccount
{
override protected void Transfer(
BankAccount destinationAccount,
User authorizedUser,
decimal amount) { }
public static void Main()
{
User drEvil = new User("Dr. Evil");
BankAccount yours = new SwissBankAccount(1234567);
BankAccount mine = new SwissBankAccount(66666666);
yours.DoTransfer(mine, drEvil, 1000000.00m); // compilation error
// You don't have the right to access the protected member of
// SwissBankAccount just because you are in a
// type derived from BankAccount.
}
}
当你提出什么似乎像一个没有脑子,如果允许再发生那种有心计的,你在这里看到的将是可能的。现在你知道受保护的方法调用要么来自你的类型(你可以控制),要么来自你直接继承的类(你在编译时知道)。如果它向任何从声明类型继承的人打开,那么你永远不会知道可以调用受保护方法的类型。
当您将您的BaseClass
变量初始化为您自己的类的实例时,编译器只会看到变量类型为BaseClass
,这使您处于信任圈之外。编译器不会分析所有的分配调用(或潜在的分配调用)以确定它是否“安全”。
Thanks Adam :)这真的很有帮助。 – DotNetGuy 2010-01-21 17:19:16
@DotNetGuy:谢谢;如果这回答您的问题,请记住将其标记为您接受的答案,以便其他人可以更轻松地找到答案。 – 2010-01-21 17:36:37