Eric Lippert chỉ blogged on this very topic.
Ý chính cơ bản của nó là để đảm bảo rằng một lớp có thể "tin tưởng" người gọi của một phương pháp được bảo vệ. Các lớp chia sẻ một lớp cơ sở chung - ngay cả khi cơ sở chung đó định nghĩa phương thức được bảo vệ - về cơ bản là những người lạ trong vấn đề này.
Ví dụ của Eric dựa trên ý tưởng về đơn đăng ký ngân hàng. Thay vì tái tạo gương sáng của mình, tôi chỉ sẽ nôn ra nó ở đây:
// 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.
}
}
Trong khi những gì bạn trình bày có vẻ như không có trí tuệ, nếu nó được phép xảy ra sau đó các loại shenanigans bạn thấy ở đây sẽ có thể. Ngay bây giờ, bạn biết rằng cuộc gọi phương thức được bảo vệ đến từ loại của bạn (mà bạn có quyền kiểm soát) hoặc từ một lớp mà bạn trực tiếp kế thừa từ (mà bạn biết tại thời điểm bạn biên dịch). Nếu nó được mở cho bất kỳ ai thừa hưởng từ kiểu khai báo, thì bạn sẽ không bao giờ có sự bảo đảm khi biết các kiểu có thể gọi phương thức được bảo vệ của bạn.
Trong khi bạn đang khởi tạo biến số BaseClass
cho một phiên bản của lớp của riêng bạn, trình biên dịch chỉ thấy biến đó thuộc loại BaseClass
, đưa bạn ra khỏi vòng tròn tin cậy. Trình biên dịch không phân tích tất cả các cuộc gọi chuyển nhượng (hoặc các cuộc gọi chuyển nhượng tiềm năng) để xác định xem nó có "an toàn" hay không.
Nguồn
2010-01-21 16:23:00
Cảm ơn Adam :) Điều đó thực sự hữu ích. – DotNetGuy
@DotNetGuy: Cảm ơn; nếu điều này trả lời câu hỏi của bạn, hãy nhớ đánh dấu câu hỏi đó là câu trả lời được chấp nhận của bạn để người khác có thể dễ dàng tìm thấy câu trả lời. –