2011-12-20 19 views
19

Nếu tôi thay đổi công cụ sửa đổi truy cập của người đặt công khai từ tư nhân thành công khai, có phải là nguyên nhân gây ra bất kỳ thay đổi đột phá nào trong các hội đồng khác tham chiếu không?Đây có phải là thay đổi đột phá làm thay đổi công cụ sửa đổi quyền truy cập của thuộc tính công cộng không?

+0

Không, những hội đồng khác chưa bao giờ có thể sử dụng thuộc tính trước đây. –

+0

@Hans, getter của tài sản là công khai để hội đồng khác có thể sử dụng nó. – mkus

+0

Vâng, bạn không thay đổi getter là bạn? Trình biên dịch JIT không có bất kỳ rắc rối nào với việc khai báo thuộc tính đã thay đổi. –

Trả lời

31

CẬP NHẬT: This question was the topic of my blog in January 2012. Cảm ơn vì câu hỏi tuyệt vời của bạn!


Tôi giả định rằng bằng "thay đổi đột ngột" nghĩa là "khi tôi biên dịch lại mã phụ thuộc vào hội đồng này, mã nào được sử dụng để biên dịch vẫn biên dịch?"

Theo định nghĩa đó, nghiêm túc nói, vâng, làm cho một công ty thiết lập thuộc tính được sử dụng là riêng tư là một sự thay đổi đột phá. Giả sử bạn có mã này:

// Assembly Alpha 
public class Charlie 
{ 
    public int P { get; private set; } 
} 
public class Delta 
{ 
    public int P { get; set; } 
} 

Và sau đó trong lắp ráp khác tham chiếu Alpha:

// Assembly Echo 
class Foxtrot 
{ 
    static void M(Action<Charlie> f) {} 
    static void M(Action<Delta> f) {} 
    static void Golf() 
    { 
     M(y=>{y.P = 123;}); 
    } 
} 

Bạn biên dịch assembly Echo. Lớp Foxtrot có một phương pháp Golf mà quá tải độ phân giải trên M. M có hai quá tải; một trong đó có một hành động trên Charlie và một trong đó có một hành động trên Delta. Nếu tham số lambda y là kiểu Charlie thì thân lambda tạo ra một lỗi khả năng truy cập, và do đó tình trạng quá tải của M không phải là một ứng cử viên áp dụng. Độ phân giải quá tải chọn quá tải và biên dịch thứ hai thành công.

Bây giờ bạn thay đổi lắp ráp Alpha để thiết lập của Charlie.P là công khai. Bạn biên dịch lại Echo. Bây giờ bạn nhận được một lỗi độ phân giải quá tải bởi vì cả hai tình trạng quá tải của M đều có giá trị như nhau và không tốt hơn cái kia. Biên dịch Echo không thành công do sự thay đổi trong Alpha. Thay đổi của bạn đối với Alpha là một thay đổi đột phá.

Câu hỏi không phải là "đây có phải là thay đổi đột ngột không?" Rõ ràng là; hầu hết mọi thay đổi là một loại thay đổi đột phá. Câu hỏi đặt ra là liệu sự thay đổi đột phá trên thực tế có thực sự phá vỡ bất kỳ ai hay không, và nếu vậy, chi phí sửa chữa điểm ngắt so với lợi ích của tính năng mới là gì?

+2

Điều gì đã xảy ra với Bravo? – kvb

+20

@kvb: Tôi đã từng gọi điện thoại cho hãng hàng không để thay đổi đặt chỗ và người phụ nữ hữu ích trên điện thoại cho biết "và đây là số xác nhận của bạn nếu có sự cố: 153ADN6, đó là 1-5-3-Alpha-Dog-November- 6 ", và tôi nói" Cảm ơn, nhưng không phải là Delta từ mã phát thanh quốc tế cho D? " và cô ấy nói "* Chúng tôi không nói từ đó tại hãng hàng không này! *" Tôi nói với bạn, nhận được * người * trên điện thoại tại một hãng hàng không là đủ cứng; nhận được một người thông minh và hài hước, những người biết bảng chữ cái radio quốc tế để khởi động là một điều hiếm có. –

+2

Sẽ hài hước hơn nếu đó thực sự là Delta bạn đang gọi. –

5

Điều này tùy thuộc vào mức độ nghiêm ngặt mà bạn muốn trở thành "phá vỡ thay đổi".

Một định nghĩa là: nó có phá vỡ việc xây dựng hoặc thực hiện mã giới thiệu hay không.

Khác là, mã khác có thể xác định rằng bạn đã thực hiện thay đổi hay không.

Theo định nghĩa đầu tiên, đây không phải là thay đổi đột phá. Theo định nghĩa thứ hai, đó là một thay đổi phá vỡ.

+1

[Câu trả lời của Eric] (http://stackoverflow.com/a/8581029) và [Câu trả lời của Jeffrey] (http://stackoverflow.com/a/8581019) cung cấp các trường hợp cạnh mà nó sẽ phá vỡ biên dịch. – Brian

0

tôi không nghĩ nhưng bạn nên biết sự khôn ngoan đằng sau để làm cho thiết lập riêng này là gì. các công cụ sửa đổi truy cập rất quan trọng đối với người tiêu dùng thư viện và trong việc đóng gói.

3

Nó có thể là, nếu những hội đồng khác sử dụng sự phản chiếu để kiểm tra sự hiện diện của setter.

Nhưng mã bị ràng buộc sớm sẽ không bị hỏng.

Một điều cần xem xét là liệu đây có phải là thay đổi về ngữ nghĩa hay không. Nếu thuộc tính trước đây chỉ được đặt trong khi xây dựng và giờ đây có thể được sửa đổi bất kỳ lúc nào, điều đó chắc chắn có thể phá vỡ người tiêu dùng đã lưu trữ giá trị, sử dụng nó làm khóa Từ điển, v.v.

2

Do khả năng hiển thị của thuộc tính được tăng lên bây giờ không nên có bất kỳ vấn đề với hội đồng liên kết tĩnh và tài liệu tham khảo tĩnh - những hội đồng chỉ xử lý tài sản của bạn như là chỉ đọc cho đến bây giờ và họ tiếp tục làm như vậy.

Vấn đề duy nhất có khả năng xảy ra ở đây là nếu một số hội đồng sử dụng phản chiếu để nhận thông tin về thuộc tính của bạn và thực hiện một số hành động.

Ví dụ, nếu đây là một tài sản của một đối tượng kinh doanhbạn sử dụng dữ liệu ràng buộc để hiển thị dữ liệu của bạn trong một số kiểm soát, như GridView hoặc ListView (độc lập với khuôn khổ thực tế), nó có thể là rằng đây tài sản sẽ được công nhận là "updateable" bây giờ và người dùng có thể thay đổi một số giá trị bạn (và một số hội đồng khác) được coi là bất biến cho đến nay.

17

Đó là một thay đổi đột phá, ở chỗ nó có thể khiến mã hiện tại không còn biên dịch.

Một số ngôn ngữ không cho phép bạn ghi đè thuộc tính mà không ghi đè tất cả người truy cập hiển thị. VB là một ngôn ngữ như vậy.

Giả sử bạn có các lớp học C# sau:

namespace TestLibrary 
    public class A { 
     public virtual int X { 
      get { return 0; } 
      private set { Console.WriteLine("A.set_X called."); } 
     } 
    } 
} 

Trong một dự án VB tham chiếu đến thư viện của bạn, bạn có một định nghĩa lớp:

Class B : Inherits TestLibrary.A 
    Public Overrides ReadOnly Property X As Integer 
     Get 
      Return MyBase.X 
     End Get 
    End Property 
End Class 

Thông báo các ReadOnly sửa đổi trên tài sản. Điều này là bắt buộc trong VB, bởi vì bạn chỉ xác định getter.Nếu bạn để nó ra, bạn nhận được một lỗi thời gian biên dịch:

Property without a 'ReadOnly' or 'WriteOnly' specifier must provide both a 'Get' and a 'Set'.

Bây giờ, loại bỏ các private modifier từ setter trong C# lớp:

namespace TestLibrary 
    public class A { 
     public virtual int X { 
      get { return 0; } 
      set { Console.WriteLine("A.set_X called."); } 
     } 
    } 
} 

Bây giờ bạn sẽ có được một thời gian biên dịch lỗi trong mã VB của bạn:

'Public Overrides ReadOnly Property X As Integer' cannot override 'Public Overridable Property X As Integer' because they differ by 'ReadOnly' or 'WriteOnly'.

Mã tương tự tham chiếu đến thư viện của bạn không biên dịch sau khi bạn thực hiện thay đổi, do đó thay đổi đột ngột.

+5

Tốt nhất! Ngắt ngôn ngữ là một số khó khăn nhất. –

+0

Tôi thực sự ghét cách tính chất được thực hiện trong.mạng lưới; Lợi ích thực sự của tôi là có ba kiểu thuộc tính, một trong số đó bao gồm hai phương thức, thay vì chỉ đơn giản là có các thuộc tính và các bộ định vị là các phương thức với một số thuộc tính cho biết rằng, với mục đích cú pháp, gỡ lỗi hiển thị, tuần tự hóa, vv nên được coi là tài sản? Nếu nó có thể cho một thói quen chấp nhận một tham số kiểu 'Property ', tôi có thể thấy một số lợi ích thực sự để có getter và setter liên kết với nhau như một thực thể duy nhất, nhưng nó không phải là. Vậy lợi ích là gì? – supercat

+0

@supercat Đó chính xác là cách các thuộc tính hoạt động trong .NET: IL không bao giờ gọi các thuộc tính, chỉ các phương thức. Các thuộc tính chỉ tồn tại trong metatada. Thực tế là các phương thức getter và setter không dễ truy cập là vấn đề thiết kế ngôn ngữ: chúng là các phương thức công khai nhưng bị ẩn bởi hầu hết các ngôn ngữ bởi vì chúng có thuộc tính 'SpecialName'. Tại sao C# ngăn cản bạn gọi những phương thức này một cách rõ ràng, tôi không biết. –

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