151 votes

Pourquoi "decimal" n'est pas un type de paramètre d'attribut valide ?

C'est vraiment incroyable mais réel. Ce code ne fonctionnera pas :

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

Pendant que ça marche :

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

Qui peut me dire pourquoi le double est acceptable alors que le décimal ne l'est pas ?

1 votes

154voto

GenericTypeTea Points 27689

Il s'agit d'une restriction du CLR. Seul constantes primitives ou tableaux de primitives peuvent être utilisées comme paramètres d'attribut. La raison en est qu'un doit être entièrement codé en métadonnées. C'est différent du corps d'une corps de la méthode qui est codé en IL. L'utilisation des métadonnées ne fait que restreindre sévèrement la portée des valeurs qui peuvent être utilisées. Dans la version actuelle du CLR, les valeurs de métadonnées sont limitées à primitives, null, types et tableaux de primitives (j'ai peut-être oublié un mineur).

Tiré de ce réponse par JaredPar .

Les décimales, bien qu'étant un type de base, ne sont pas un type primitif. type primitif et ne peuvent donc pas être représenté dans les métadonnées, ce qui l'empêche d'être un paramètre d'attribut.

38 votes

Pourquoi les décimales ne sont pas considérées comme des types primitifs dans le CLR ?

10 votes

@koumides je crois que la réponse est que le type est trop grand pour être exprimé dans un seul registre du CPU car il est de 128bit.

3 votes

OK, pourquoi les chaînes de caractères sont-elles autorisées comme propriétés d'attribut ? Je suppose qu'elles entrent dans la catégorie des "tableaux de primitives", mais elles sont allouées au tas (type référence)...

67voto

Kobi Points 65357

De la Spécifications :

Les types de paramètres positionnels et nommés pour une classe d'attributs sont limités aux types de paramètres d'attributs, qui sont :

  • Un des types suivants : bool , byte , char , double , float , int , long , sbyte , short , string , uint , ulong , ushort .
  • Le type object .
  • Le type System.Type .
  • Un type d'énumération, à condition qu'il ait une accessibilité publique et que les types dans lesquels il est imbriqué (le cas échéant) aient également une accessibilité publique (spécification des attributs).
  • Tableaux unidimensionnels des types ci-dessus.

10 votes

Correct, mais notez que vous citez une ancienne version de la spécification. Dans les versions 3.0, 4.0 et 5.0 de C#, il est indiqué qu'il peut également avoir le type sbyte , ushort , uint , ulong . Et cela semble fonctionner correctement. Mais encore decimal n'est pas autorisé :-(

1 votes

@JeppeStigNielsen J'ai mis à jour le lien vers les spécifications et la citation.

6 votes

Les primitives annulables ne sont pas non plus prises en charge.

3voto

Daniel Barbalace Points 1049

La réponse à ce problème est d'utiliser des chaînes de caractères, qui sont autorisées comme attributs bien qu'elles ne soient pas un type atomique. N'utilisez pas de doubles, car l'arrondi rendrait les résultats moins précis.

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

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

private decimal minimumValueDecimal;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X