2010-11-05 41 views
18

Có thể sử dụng thuộc tính Obsolete trên chỉ một getter hoặc một setter của một tài sản không?Chỉ có thể sử dụng thuộc tính Lỗi thời trên chỉ một getter hoặc một setter của một thuộc tính

Tôi muốn để có thể làm điều gì đó như thế này:

public int Id { 
    get { return _id;} 
    [Obsolete("Going forward, this property is readonly",true)] 
    set { _id = value;} 
} 

nhưng rõ ràng rằng sẽ không xây dựng. Có một công việc xung quanh đó cho phép tôi áp dụng thuộc tính này cho chỉ setter?

+1

Vì bạn đã đặt giá trị này để tăng lỗi, tại sao không chỉ xóa bộ đặt, chúng sẽ được thông báo chỉ đọc. – Doggett

+1

Bạn vẫn có thể tắt lỗi bằng cách sử dụng lệnh '#pragma warning', mặc dù nó không chỉ là cảnh báo. Bằng cách đó mã di sản vẫn sẽ xây dựng, trong khi mã tương lai thì không. –

Trả lời

9

Tôi nghĩ rằng điều này không thể thực hiện được vì, vì một lý do nào đó, nó không được phép cụ thể cho thuộc tính Lỗi thời. Theo các quy tắc được xác định xung quanh các mục tiêu thuộc tính, có vẻ như không có bất kỳ lý do nào mà thuộc tính Obsolete sẽ không hợp lệ trên một thuộc tính get hoặc set accessor. Để áp dụng thuộc tính cho một bộ truy cập được đặt thuộc tính, that attribute must be applicable to either a method, parameter, or return value target. Nếu bạn nhìn vào the Obsolete attribute, bạn có thể thấy rằng "phương pháp" là một trong những mục tiêu hợp lệ cho thuộc tính đó.

Thực tế, bạn có thể xác định thuộc tính của riêng bạn với cùng mục tiêu hợp lệ như thuộc tính lỗi thời with the AttributeUsage attribute và bạn sẽ thấy nó có thể áp dụng hoặc đặt accessor trong khi bạn không thể áp dụng thuộc tính lỗi thời.

[AttributeUsage(AttributeTargets.Method)] 
class MyMethodAttribute : Attribute { } 

class MyClass 
{ 
    private int _Id; 

    public int Id 
    { 
     get { return _Id; } 

     [MyMethodAttribute] // this works because "Method" is a valid target for this attribute 
     [Obsolete] // this does not work, even though "Method" is a valid target for the Obsolete attribute 
     set { _Id = value; } 
    } 
} 

Nếu bạn cố gắng tạo ra thuộc tính của riêng bạn mà không có giá trị trên một accessor bộ tài sản và bạn áp dụng nó ở đó, sau đó bạn có thể nhận thấy thông báo lỗi là hơi khác nhau. Thông báo lỗi cho thuộc tính tùy chỉnh của bạn sẽ là "Thuộc tính" YourCustomAttribute 'không hợp lệ trên loại khai báo này ", trong khi thông báo lỗi cho thuộc tính Lỗi thời là" Thuộc tính "Lỗi thời" không hợp lệ trên thuộc tính hoặc trình truy cập sự kiện. " Thực tế là thông báo lỗi khác nhau khiến tôi tin rằng đây là một quy tắc, vì lý do gì đó, được xây dựng một cách rõ ràng vào trình biên dịch cho thuộc tính Lỗi thời, thay vì dựa vào thuộc tính AttributeUsage, được cho là, được áp dụng cho thuộc tính Lỗi thời .

+0

'ObsoletteAttribute' là' sealed' ... – Shimmy

+1

@Shimmy Tôi đã không gợi ý lấy một lớp từ 'ObsoleteAttribute', nhưng chỉ giải thích các quan sát khiến tôi tin rằng hạn chế này về việc sử dụng thuộc tính Lỗi thời được xác định bởi việc thực hiện trình biên dịch, chứ không phải quy tắc sử dụng thuộc tính .NET. Tôi không chắc tại sao lớp học lại bị niêm phong. –

+0

@ Dr.Willy, tôi đã bỏ lỡ nó xin lỗi ... Tôi có một tài sản tôi cần nó để được đọc-ghi, nhưng không muốn viết được sử dụng, tôi chỉ cần thực hiện một yêu cầu hợp đồng, 'ObsoleteAttribute' có thể tiện dụng ở đây. – Shimmy

0

Tôi đã có cùng một vấn đề ngày hôm nay và có giải pháp làm việc cho các đối tượng dữ liệu đơn giản không có bất kỳ logic riêng nào. Thay vì làm cho setter lỗi thời (mà không làm việc vì những lý do được đề cập trong câu trả lời khác), tôi đã tự tạo ra constructor lỗi thời và giới thiệu một cái mới mà tôi cung cấp giá trị ban đầu. Điều này giả định constructor mặc định đã được chạy để tạo ra cá thể của lớp. Có lẽ bạn sẽ phải đánh dấu một cái khác.

Tuy nhiên chúng tôi can't sử dụng tính năng tự động thực hiện trong trường hợp này để có thể thiết lập giá trị ban đầu trong xây dựng:

class MyClass 
{ 
    [Obsolete("Use the constructor with param myProperty instead")] MyClass() { } 
    MyClass(MyProperty m) { this.m_MyProperty = m; } 

    public MyType MyProperty 
    { 
     get { return this.m_MyProperty; } 
     set { this.m_MyProperty = value; } 
    } 
} 

Vì vậy, trong thực tế, tôi đã tạo ra một readonly-tài sản có giá trị có thể chỉ được thiết lập bởi hàm tạo. Bất kỳ attemp để tạo ra một thể hiện theo mặc định-constructor của nó và thiết lập thuộc tính của nó sẽ không tạo ra các trình biên dịch cảnh báo cho các setter nhưng đối với instantiation - đó là ổn trong trường hợp của tôi:

var m = new MyClass(); // here we get warning/error now 
m.MyProperty = 

Hãy nhận biết rằng doesn này ´ không hoạt động nếu tài sản của bạn không được thiết lập từ số bên ngoài. Đây là khi giá trị của nó được tính bằng mã mới của bạn:

MyProperty { get { return /* some computation */ } } 
Các vấn đề liên quan