2012-01-18 29 views
8

Đây là những mô hình phổ biến và chỉ nhất mà tôi đã thấy cho đến nay:Cú pháp nào được phép khi áp dụng các thuộc tính C#?

[AttributeFoo] 
[AttributeBar("Hello world!")] 
[AttributeBaz(foo=42,bar="Hello world!")] 
public class Example {} 

Cú pháp thuộc tính trông giống như bạn đang gọi một constructor. Và trước khi C# hỗ trợ các đối số tùy chọn và được đặt tên, các tham số được đặt tên cho các thuộc tính là sự khác biệt duy nhất có thể nhìn thấy.

Trình biên dịch C# có cho phép gì khác không? Giống như params đối số hoặc bộ khởi tạo đối tượng/bộ sưu tập?

Xem thêm: Applying Attributes trên MSDN

+0

Tôi đã đặt trình khởi tạo 'string []' vào một thuộc tính. – JohnL

Trả lời

3

AFAIK, thông số được đặt tên chỉ cho phép loại tích phân. Thật không may tôi không có một tham chiếu để trở lại này, tôi chỉ học được nó thông qua thử nghiệm của riêng tôi.

Khi cố gắng sử dụng initialisers đối tượng, tôi đã nhận lỗi này từ trình biên dịch:

Một cuộc tranh cãi thuộc tính phải là một biểu thức hằng số, typeof biểu hiện hoặc tạo mảng biểu hiện của một loại tham số thuộc tính

Mặc dù điều này documentation là một vài năm tuổi, nó có thông tin tham khảo tôi đang tìm kiếm:

Thuộc tính p arameters bị hạn chế giá trị không đổi của loại sau đây:

  • loại đơn giản (bool, byte, char, short, int, long, float, và đôi)
  • chuỗi
  • System.Type
  • enums
  • đối tượng (Đối số tham số thuộc tính của đối tượng kiểu phải là giá trị không đổi của một trong các loại ở trên.) Một chiều mảng của bất kỳ của các loại trên

Vì vậy, công trình này:

//Test attribute class 
[AttributeUsage(AttributeTargets.All)] 
internal class TestAttribute : Attribute 
{ 
    public int[] Something { get; set; } 
} 

//Using an array initialiser - an array of integers 
[TestAttribute(Something = new int[]{1, 2, 3, 4, 5})] 
public abstract class Something 

Trong khi điều này sẽ không:

//Test person class 
internal class Person 
{ 
    public string Name { get; set; } 

    public Person(string name) 
    { 
     this.Name = name; 
    } 
} 

//Test attribute class 
[AttributeUsage(AttributeTargets.All)] 
internal class TestAttribute : Attribute 
{ 
    public IEnumerable<Person> Something { get; set; } 
} 

//This won't work as Person is not an integral type 
[TestAttribute(Something = new Person[]{new Person("James")})] 

EDIT: chỉ để xây dựng, các thuộc tính tạo thành một phần của siêu dữ liệu cho các cấu trúc mà chúng được áp dụng cho (trong IL được tạo), do đó các thành viên của lớp thuộc tính phải được xác định tại thời gian biên dịch; do đó hạn chế về tham số thuộc tính đối với các giá trị không đổi.

0

thông số Positional được yêu cầu và phải đến trước khi bất kỳ thông số được đặt tên; chúng tương ứng với các tham số của một trong các hàm tạo của thuộc tính. Các tham số được đặt tên là tùy chọn và tương ứng với thuộc tính đọc/ghi của thuộc tính. Trong C++, C# và J #, chỉ định tên = giá trị cho mỗi tham số tùy chọn, trong đó name là tên của thuộc tính. Trong Visual Basic, chỉ định tên: = giá trị.

Từ liên kết bạn đã cung cấp. Có vẻ như đó là những thứ duy nhất được cho phép. Về cơ bản bạn đang kết hợp constructor với logic khởi tạo thuộc tính nhúng, như bạn đã đề cập.

3

Ngoài những gì người khác đã nói, tôi muốn chỉ ra rằng các thuộc tính cũng có thể được phân cách bằng dấu phẩy.

[AttributeFoo, AttributeBar("Hello world!"), AttributeBaz(foo=42,bar="Hello world!")] 
public class Example {} 
+2

Đây là một thực tế không tốt; nó ít dễ đọc hơn. – Jowen

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