Tại sao thập phân thập phân không phải là một loại tham số thuộc tính hợp lệ?


139

Nó thực sự không thể tin được nhưng có thật. Mã này sẽ không hoạt động:

[AttributeUsage(AttributeTargets.Property|AttributeTargets.Field)]
public class Range : Attribute
{
    public decimal Max { get; set; }
    public decimal Min { get; set; }
}

public class Item
{
    [Range(Min=0m,Max=1000m)]  //compile error:'Min' is not a valid named attribute argument because it is not a valid attribute parameter type 
    public decimal Total { get; set; }  
}

Trong khi điều này hoạt động:

[AttributeUsage(AttributeTargets.Property|AttributeTargets.Field)]
public class Range : Attribute
{
    public double Max { get; set; }
    public double Min { get; set; }
}

public class Item
{
    [Range(Min=0d,Max=1000d)]
    public decimal Total { get; set; }  
}

Ai có thể cho tôi biết tại sao tăng gấp đôi là OK trong khi số thập phân thì không.


Câu trả lời:


139

Đây là một hạn chế CLR. Chỉ các hằng hoặc mảng nguyên thủy có thể được sử dụng làm tham số thuộc tính. Lý do tại sao một thuộc tính phải được mã hóa hoàn toàn trong siêu dữ liệu. Điều này khác với phần thân phương thức được mã hóa trong IL. Sử dụng MetaData chỉ hạn chế nghiêm ngặt phạm vi của các giá trị có thể được sử dụng. Trong phiên bản hiện tại của CLR, các giá trị siêu dữ liệu được giới hạn ở các nguyên hàm, null, các loại và các mảng nguyên thủy (có thể đã bỏ lỡ một giá trị nhỏ).

Lấy từ câu trả lời này của JaredPar .

Số thập phân trong khi một loại cơ bản không phải là loại nguyên thủy và do đó không thể được biểu diễn trong siêu dữ liệu, điều này ngăn nó trở thành một tham số thuộc tính.


34
Tại sao số thập phân không được coi là loại nguyên thủy trong CLR?
koumides

10
@koumides Tôi tin rằng câu trả lời là loại quá lớn để thể hiện trong một thanh ghi CPU vì nó là 128 bit
Chris Marisic

2
OK vậy tại sao các chuỗi được phép làm thuộc tính? Tôi cho rằng nó thuộc danh mục 'mảng nguyên thủy' nhưng nó được phân bổ heap (loại tham chiếu) ...
Steztric

Bởi vì các chuỗi là các loại tham chiếu được xử lý hoàn toàn khác nhau.
Carsten Schütte

2
@ Điều này không đúng, Enumđược hỗ trợ. Tôi hiện có 2 thuộc tính tùy chỉnh một với 2 enum và các thuộc tính khác với một mảng enum.
Franck

60

Từ thông số kỹ thuật :

Các loại tham số vị trí và được đặt tên cho một lớp thuộc tính được giới hạn trong các loại tham số thuộc tính, đó là:

  • Một trong các loại sau: bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort.
  • Các loại object.
  • Các loại System.Type.
  • Một loại enum, miễn là nó có khả năng truy cập công khai và các loại mà nó được lồng (nếu có) cũng có khả năng truy cập công khai (Đặc tả thuộc tính).
  • Mảng một chiều của các loại trên.

10
Đúng, nhưng lưu ý rằng bạn đang trích dẫn một phiên bản cũ của thông số kỹ thuật. Trong C # phiên bản 3.0, 4.0, và 5.0, người ta nói rằng nó cũng có thể có loại sbyte, ushort, uint, ulong. Và điều đó dường như làm việc tốt. Nhưng vẫn decimalkhông được phép :-(
Jeppe Stig Nielsen

1
@JeppeStigNielsen Tôi đã cập nhật liên kết và trích dẫn thông số
Ohad Schneider

6
Nguyên thủy Nullable cũng KHÔNG được hỗ trợ.
KTCO

2

Câu trả lời cho vấn đề này là sử dụng các chuỗi, được phép làm thuộc tính mặc dù không phải là loại nguyên tử. Đừng sử dụng gấp đôi vì làm tròn sẽ làm cho kết quả kém chính xác hơn.

public String MinimumValue
{
    get
    {
        return minimumValueDecimal.ToString();
    }

    set
    {
        minimumValueDecimal = Decimal.Parse(value);
    }
}

private decimal minimumValueDecimal;
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.