Tôi có thể khởi tạo thuộc tính C # với một mảng hoặc số đối số biến khác không?


105

Có thể tạo một thuộc tính có thể được khởi tạo với một số đối số thay đổi không?

Ví dụ:

[MyCustomAttribute(new int[3,4,5])]  // this doesn't work
public MyClass ...

12
Bạn chỉ có cú pháp của bạn cho mảng sai. Nó phải là "new int [] {3,4,5}".
David Wengier

Câu trả lời:


178

Các thuộc tính sẽ nhận một mảng. Mặc dù nếu bạn kiểm soát thuộc tính, bạn cũng có thể sử dụng paramsthay thế (tốt hơn đối với người tiêu dùng, IMO):

class MyCustomAttribute : Attribute {
    public int[] Values { get; set; }

    public MyCustomAttribute(params int[] values) {
       this.Values = values;
    }
}

[MyCustomAttribute(3, 4, 5)]
class MyClass { }

Cú pháp tạo mảng của bạn chỉ xảy ra:

class MyCustomAttribute : Attribute {
    public int[] Values { get; set; }

    public MyCustomAttribute(int[] values) {
        this.Values = values;
    }
}

[MyCustomAttribute(new int[] { 3, 4, 5 })]
class MyClass { }

33

Bạn có thể làm điều đó, nhưng nó không tuân thủ CLS:

[assembly: CLSCompliant(true)]

class Foo : Attribute
{
    public Foo(string[] vals) { }
}
[Foo(new string[] {"abc","def"})]
static void Bar() {}

Trình diễn:

Warning 1   Arrays as attribute arguments is not CLS-compliant

Đối với việc sử dụng phản chiếu thường xuyên, có thể tốt hơn nếu có nhiều thuộc tính, tức là

[Foo("abc"), Foo("def")]

Tuy nhiên, điều này sẽ không hoạt động với TypeDescriptor/ PropertyDescriptor, trong đó chỉ một phiên bản duy nhất của bất kỳ thuộc tính nào được hỗ trợ (chiến thắng đầu tiên hoặc cuối cùng, tôi không thể nhớ cái nào).


3
lưu ý: nhiều thuộc tính yêu cầu thuộc tính AttributeUsage trên thuộc tính của bạn. stackoverflow.com/questions/553540/…
russau

23

Hãy thử khai báo hàm tạo như sau:

public class MyCustomAttribute : Attribute
{
    public MyCustomAttribute(params int[] t)
    {
    }
}

Sau đó, bạn có thể sử dụng nó như:

[MyCustomAttribute(3, 4, 5)]


12

Điều đó sẽ không sao. Từ thông số kỹ thuật, phần 17.2:

Biểu thức E là một thuộc tính-đối số-biểu thức nếu tất cả các câu lệnh sau đều đúng:

  • Kiểu của E là một kiểu tham số thuộc tính (§17.1.3).
  • Tại thời điểm biên dịch, giá trị của E có thể được giải quyết thành một trong những điều sau:
    • Một giá trị không đổi.
    • Một đối tượng System.Type.
    • Mảng một chiều gồm các biểu thức thuộc tính-đối số .

Đây là một ví dụ:

using System;

[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public class SampleAttribute : Attribute
{
    public SampleAttribute(int[] foo)
    {
    }
}

[Sample(new int[]{1, 3, 5})]
class Test
{
}

5
Mặc dù vậy, hãy chú ý tuân thủ CLS
Marc Gravell

4

Có, nhưng bạn cần khởi tạo mảng mà bạn đang chuyển vào. Đây là một ví dụ từ kiểm tra hàng trong kiểm tra đơn vị của chúng tôi để kiểm tra một số tùy chọn dòng lệnh thay đổi;

[Row( new[] { "-l", "/port:13102", "-lfsw" } )]
public void MyTest( string[] args ) { //... }

2

Bạn có thể làm điều đó. Một ví dụ khác có thể là:

class MyAttribute: Attribute
{
    public MyAttribute(params object[] args)
    {
    }
}

[MyAttribute("hello", 2, 3.14f)]
class Program
{
    static void Main(string[] args)
    {
    }
}

1

Để giải thích lại câu trả lời của Marc Gravell, có, bạn có thể xác định một thuộc tính với các tham số mảng nhưng việc áp dụng một thuộc tính với một tham số mảng không tuân thủ CLS. Tuy nhiên, chỉ cần xác định một thuộc tính với một thuộc tính mảng là hoàn toàn tuân thủ CLS.

Điều khiến tôi nhận ra điều này là Json.NET, một thư viện tuân theo CLS, có lớp thuộc tính JsonPropertyAttribute với thuộc tính có tên ItemConverterParameters, đó là một mảng các đối tượng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.