在C#中使用十进制值作为属性参数?

90

我一直在尝试将十进制值用作字段属性的参数,但是我收到了编译器错误。

我发现这篇博客文章链接说在.NET中不可能使用它们,有人知道为什么选择这样做或者我如何使用十进制参数吗?


可能是为什么“decimal”不是有效的属性参数类型?的重复问题。 - StayOnTarget
5个回答

134

这是一个CLR(Common Language Runtime)限制。只有基元常量或基元数组可以用作属性参数。原因在于,属性必须完全编码为元数据,而这与使用IL编码的方法体不同。仅使用MetaData严重限制了可使用的值范围。在当前版本的CLR中,元数据值仅限于基元、null、类型和基元数组(可能错过了一些小的值)。

虽然十进制数是一种基本类型,但它不是一种基元类型,因此无法在元数据中表示,这导致它无法成为属性参数。


5
这个问题在框架4.0、4.5、4.6.x版本中仍存在吗? - midspace
@midspace,这并不是一个问题,而是一种设计上的限制。很遗憾,但很有可能它永远不会消失。 - Bruno Brant
2
只有原始常量或原始数组可以用作属性参数。但似乎并不完全准确,例如 System.Type 也是允许的:https://msdn.microsoft.com/en-us/library/aa664615(v=vs.71).aspx - DixonD
仅使用元数据会严重限制可用值的范围 - 但为什么呢?元数据可以用于指向类型定义。例如,在常规类中定义字段时,会发出包括字段名称和其类型(任何类型,而不仅仅是原始类型)的元数据。我不明白为什么这不能用于属性。 - wingerse

20

我有同样的问题。我考虑使用字符串。这不是类型安全的,但它很容易阅读,而且我认为我们能够在字符串中编写有效的数字 :-)

class BlahAttribute : Attribute
{
  private decimal value;

  BlahAttribute(string number)
  {
    value = decimal.Parse(number, CultureInfo.InvariantCulture);
  }
}

[Blah("10.23")]
class Foo {}

它可能不美观,但在考虑所有选择后,已经足够好了。


1
看起来这就是 mbUnit 的应对方式 http://vkreynin.wordpress.com/2007/05/25/mbunit-24-rtm-now-you-can-use-decimals-in-row-attributes/ - Andy Dent

2

当我遇到这种情况时,最终我将属性公开为Double类型,但在属性内部将其视为Decimal类型。虽然远非完美,但对于简单的情况,这可能就是您需要的。


1

对于属性的实时技巧,我正在使用TypeConverter类。


-1

您可以使用以下构造函数。当您在 C# 代码中有一个十进制字面量时,C# 编译器会发出对此构造函数的调用。

Decimal(Int32, Int32, Int32, Boolean, Byte)

编辑:我知道这不太方便。


5
如果这个属性可以使用,那么我猜只用“m”后缀也可以,但实际上两者都不行(我使用System.ComponentModel.DefaultValueAttribute进行测试)。 - xr280xr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接