เหตุใด“ ทศนิยม” จึงไม่ใช่ประเภทพารามิเตอร์แอตทริบิวต์ที่ถูกต้อง


139

มันไม่น่าเชื่อจริงๆ แต่เป็นของจริง รหัสนี้จะไม่ทำงาน:

[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; }  
}

ในขณะที่ใช้งานได้:

[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; }  
}

ใครสามารถบอกฉันได้ว่าทำไมดับเบิลถึงตกลงขณะที่เลขทศนิยมไม่ใช่


1
เป็นไปได้ที่ซ้ำกันของการใช้ค่าทศนิยมเป็นพารามิเตอร์ params ใน c #?
nawfal

คำตอบ:


139

นี่เป็นข้อ จำกัด CLR ค่าคงที่ดั้งเดิมหรืออาร์เรย์ของดั้งเดิมเท่านั้นที่สามารถใช้เป็นพารามิเตอร์แอตทริบิวต์ สาเหตุที่แอตทริบิวต์ต้องเข้ารหัสทั้งหมดในข้อมูลเมตา สิ่งนี้แตกต่างจากส่วนของเมธอดที่เข้ารหัสใน IL การใช้ MetaData จะ จำกัด ขอบเขตของค่าที่สามารถใช้ได้อย่างรุนแรงเท่านั้น ในเวอร์ชันปัจจุบันของ CLR ค่าเมทาดาทาจะถูก จำกัด ไว้ที่ดั้งเดิม, null, ประเภทและอาร์เรย์ของดั้งเดิมเท่านั้น (อาจพลาดเล็กน้อย)

ที่นำมาจากนี้คำตอบโดยJaredPar

ทศนิยมในขณะที่ประเภทพื้นฐานไม่ได้เป็นประเภทดั้งเดิมและจึงไม่สามารถแสดงในเมตาดาต้าซึ่งป้องกันไม่ให้มันเป็นพารามิเตอร์แอตทริบิวต์


35
ทำไมทศนิยมไม่ถือว่าเป็นชนิดดั้งเดิมใน CLR
koumides

10
@koumides ผมเชื่อว่าคำตอบคือชนิดที่มีขนาดใหญ่เกินไปที่จะแสดงในการลงทะเบียนของ CPU เดียวมันเป็น 128bit
คริส Marisic

2
ตกลงเหตุใดจึงอนุญาตให้ใช้สตริงเป็นคุณสมบัติของคุณสมบัติ ฉันคิดว่ามันมาอยู่ภายใต้หมวดหมู่ 'array of primitives' แต่มันเป็นกองที่จัดสรร (ประเภทอ้างอิง) ...
Steztric

เนื่องจากสตริงเป็นชนิดข้อมูลอ้างอิงซึ่งจัดการแตกต่างกันโดยสิ้นเชิง
Carsten Schütte

2
@Soren นี้ไม่เป็นความจริงEnumได้รับการสนับสนุน ขณะนี้ฉันมีแอตทริบิวต์ที่กำหนดเอง 2 รายการโดยที่มี 2 enums และอื่น ๆ ที่มีอาร์เรย์ของ enum
Franck

60

จากรายละเอียด :

ชนิดของพารามิเตอร์ตำแหน่งและพารามิเตอร์ที่กำหนดชื่อสำหรับคลาสของแอ็ตทริบิวต์ถูก จำกัด เฉพาะประเภทพารามิเตอร์แอ็ตทริบิวต์ ได้แก่ :

  • หนึ่งในประเภทต่อไปนี้: bool, byte, char, double, float, int, long, sbyte, short, string, uint, ,ulongushort
  • objectประเภท
  • System.Typeประเภท
  • ประเภท enum ที่จัดให้มีการเข้าถึงสาธารณะและประเภทที่ซ้อนอยู่ (ถ้ามี) นอกจากนี้ยังมีการช่วยสำหรับการเข้าถึงสาธารณะ (ข้อมูลจำเพาะของแอตทริบิวต์)
  • อาร์เรย์มิติเดียวของประเภทข้างต้น

10
ถูกต้อง แต่โปรดทราบว่าคุณอ้างอิงข้อมูลจำเพาะเวอร์ชั่นเก่า ใน C # รุ่น 3.0, 4.0 และ 5.0 ก็จะระบุว่ายังสามารถมีประเภทsbyte, ushort, ,uint ulongและดูเหมือนว่าจะทำงานได้ดี แต่ก็ยังdecimalไม่ได้รับอนุญาต :-(
Jeppe Stig Nielsen

1
@JeppeStigNielsen ฉันได้อัพเดทลิงค์ข้อมูลและราคา
Ohad Schneider

6
ดั้งเดิมไม่สนับสนุน Nullable ยังไม่ได้รับการสนับสนุน
KTCO

2

คำตอบสำหรับปัญหานี้คือการใช้สตริงซึ่งได้รับอนุญาตเป็นแอททริบิวต์แม้จะไม่ใช่ประเภทอะตอมมิก อย่าใช้คู่ผสมเพราะการปัดเศษจะทำให้ผลลัพธ์แม่นยำน้อยลง

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

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

private decimal minimumValueDecimal;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.