Почему «десятичный» не является допустимым типом параметра атрибута? - PullRequest
121 голосов
/ 07 июля 2010

Это действительно невероятно, но реально.Этот код не будет работать:

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

Кто может сказать мне, почему double - это нормально, а decimal - нет.

Ответы [ 3 ]

122 голосов
/ 07 июля 2010

Это ограничение CLR. Только примитивные константы или массивы Примитивы могут быть использованы в качестве атрибута параметры. Причина в том, что атрибут должен быть закодирован полностью в метаданные. Это отличается от тело метода, закодированное в IL. Использование метаданных только строго ограничивает область значений, которые могут быть использованы. В текущей версии CLR, значения метаданных ограничены примитивы, нуль, типы и массивы примитивы (возможно, пропустил несовершеннолетнего один).

Взято из этого ответа от JaredPar .

Десятичные дроби, в то время как базовый тип не является примитивный тип и, следовательно, не может быть представлены в метаданных, которые предотвращают это из параметра атрибута.

49 голосов
/ 07 июля 2010

Из спецификации :

Типы позиционных и именованных параметров для класса атрибута ограничены типами параметров атрибута, которые являются:

  • Один из следующих типов: bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort.
  • Тип object.
  • Тип System.Type.
  • Тип enum при условии, что он имеет общедоступную доступность, а типы, в которые он вложен (если есть), также имеют общедоступную доступность (спецификация атрибута).
  • Одномерные массивы вышеуказанных типов.
1 голос
/ 27 января 2018

Ответом на эту проблему является использование строк, которые допускаются в качестве атрибутов, несмотря на то, что они не являются атомарными. Не используйте двойные числа, поскольку округление сделает результаты менее точными.

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

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

private decimal minimumValueDecimal;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...