2015-08-29 13 views
7

Hãy xem xét các loại sau đây:Là một thành viên nội bộ và được bảo vệ có thể có trong C#?

public class Vehicle { ... } 
public class Coverage { ... } 

public class VehicleList : IEnumerable<Vehicle> { ... } 
public class CoverageList : IEnumerable<Coverage> { ... } 

public abstract class Quote 
{ 
    protected VehicleList vehicles; 
    protected CoverageList coverages; 

    internal Quote() { ... } 

    public IReadOnlyCollection<Vehicle> Vehicles 
    { 
     get { return this.vehicles.AsReadOnly(); } 
    } 
    public IReadOnlyCollection<Coverage> Coverages 
    { 
     get { return this.coverages.AsReadOnly(); } 
    } 

    ... 
} 

public sealed class OhQuote : Quote 
{ 
    //needs to access protected fields 
    ... 
} 
public sealed class InQuote : Quote { ... } 
public sealed class MiQuote : Quote { ... } 

Quote đóng gói đầy đủ các chức năng của cả hai VehicleListCoverageList vì vậy tôi muốn đánh dấu những lớp học như internal. Vấn đề là chúng là các loại của các trường protected của lớp public. Nếu tôi đánh dấu các trường đó là protected internal thì chúng là protected HOẶC internal. Những gì tôi thực sự cần là để họ được protectedinternal (với protected được ưu tiên trong hội đồng). Bạn có thể thấy rằng không phải Quote (trong đó có một constructor internal) cũng không phải lớp con của nó (có thể là sealed) có thể được mở rộng ra ngoài lắp ráp. Tôi đã tìm ra cách để đạt được chức năng mong muốn bằng cách sử dụng giao diện công cộng nhưng muốn đảm bảo rằng không có cách nào ngắn gọn hơn.

+0

tạo thuộc tính nội bộ đóng gói trường được bảo vệ – Gusman

+0

@Gusman sẽ vẫn hiển thị trường được bảo vệ cho người tiêu dùng của lớp trong hội đồng. –

+0

Xin lỗi nhưng sau đó tôi không thực sự hiểu những gì bạn đang yêu cầu, một trường được bảo vệ sẽ luôn hiển thị với bất kỳ người tiêu dùng nào, bất kể nó được xác định ở đâu và nội dung sẽ luôn hiển thị cho tất cả các lớp trong cùng một lắp ráp, do đó, một "bảo vệ nội bộ" sẽ được hiển thị cho người tiêu dùng bên trong lắp ráp, bạn sẽ làm gì sau đó? – Gusman

Trả lời

5

Mặc dù thời gian chạy .NET hỗ trợ khái niệm này ("FamilyAndAssembly"), C# hiện không.

Điều này đã được đề xuất cho C# 6.0 dưới dạng công cụ sửa đổi truy cập private protected, nhưng đối tượng địa lý đã bị loại bỏ.

CẬP NHẬT:private protected đã được thêm vào C# 7.2.

+0

Chết tiệt, đó là chính xác những gì tôi đang tìm kiếm. Bất kỳ ý tưởng nào tại sao tính năng này bị xóa? –

+0

Trên [trang thảo luận] này (https://roslyn.codeplex.com/discussions/541194), "nmgafter" đã tuyên bố rằng "Chúng tôi không thể thêm mức bảo vệ mới này vào thời điểm này, chủ yếu là do chúng tôi không thể tìm thấy cú pháp tốt. " –

+0

Thú vị. Điều đó dường như với tôi như một lý do ngu xuẩn không phải để thực hiện một tính năng, nhưng tôi đồng ý rằng 'bảo vệ riêng tư 'ít hơn cú pháp lý tưởng. –

1

Là một phụ lục: Nếu bạn muốn không sử dụng giao diện và -Như bạn see- không có C# hỗ trợ để đạt được mục tiêu đó, nhớ: bạn luôn có thể sử dụng phản ánh làm rất kỳ lạ và những thứ kỳ lạ như thế.

Bạn có thể đặt trường thành private và sử dụng phản chiếu bạn có thể gán giá trị mới từ bất cứ nơi nào bạn muốn, chắc chắn từ các lớp dẫn xuất trong cùng một cụm.

+0

Tôi tò mò, bạn có thể đưa ra một ví dụ về cách bạn muốn làm điều này? –

1

Tôi đặt câu hỏi về nhu cầu của các lớp học có nguồn gốc của bạn để truy cập trực tiếp vào các trường của Quote.

Tôi hỏi liệu có cách nào để đạt được chức năng mong muốn mà không cần sử dụng giao diện công khai hay không.

Tôi nghĩ bạn có thể an toàn thay đổi sửa đổi trên các lĩnh vực để private và có các lớp thừa kế thao tác các lĩnh vực gián tiếp qua protected phương pháp quy định tại lớp Quote cơ sở của bạn. Không yêu cầu giao diện công cộng bổ sung.

Dưới đây là một ví dụ về những gì nó có thể trông giống như:

public class Vehicle {} 
public class Coverage {} 

// Set these as "internal" as you were hoping for... 
internal class VehicleList : IEnumerable<Vehicle> 
{ 
    public void Foo() {} 
} 

internal class CoverageList : IEnumerable<Coverage> 
{ 
    public void Bar() {} 
} 

public abstract class Quote 
{ 
    // Mark these as "private" 
    private VehicleList vehicles; 
    private CoverageList coverages; 

    internal Quote() {} 

    public IReadOnlyCollection<Vehicle> Vehicles 
    { 
     get { return this.vehicles.AsReadOnly(); } 
    } 
    public IReadOnlyCollection<Coverage> Coverages 
    { 
     get { return this.coverages.AsReadOnly(); } 
    } 

    // Add protected methods to manipulate the private fields. 
    protected void PerformFooOnVehicles() 
    { 
     this.vehicles.Foo(); 
    } 

    protected void PerformBarOnCoverages() 
    { 
     this.coverages.Bar(); 
    } 

} 

public sealed class OhQuote : Quote 
{ 
    // We now have indirect access to Quote's private fields. 
    public void Baz() 
    { 
     this.PerformBarOnCoverages(); 
     this.PerformFooOnVehicles(); 
    } 
} 
public sealed class InQuote : Quote {} 
public sealed class MiQuote : Quote {} 

Phương án này hoàn thành mục tiêu của gián tiếp lộ VehicleListCoverageListchỉ đến các lớp học có nguồn gốc là một phần của cùng một assembly.

Các vấn đề liên quan