我很困惑,因为在C#中,1.0m
之类的小数字符可以用作常量字段,但不能用作属性的参数。
[Foo(1.0m)] // Error
class C
{
const decimal constD1 = 1.0m;
}
在a thread at MSDN中,James Curran回复道:
" 1000M"仅仅是"新十进制(1000)"的简写,其中涉及到 方法调用,这意味着它不被视为常数。只是因为 编译让你假装它在大多数时间里都是常数,不会 意味着你可以随时随地。
但如果它是构造函数调用的简写,你应该能够这样做:
class C
{
const decimal constD2 = new decimal(1.0); // Error
}
如果我正确理解Jon Skeet' reply to a similar question,则无法将小数传递给属性,这意味着,我永远无法成功执行此类操作:
class FooAttribute : Attribute
{
public FooAttribute(object obj)
{
if (obj is decimal)
{
// Doomed to be dead code?
}
}
}
另见this question。 顺便说一下,ReSharper没有为属性值中的十进制常量/文字显示编译器错误,这是一个known issue。
以下是一个完整的例子:
namespace ClassLibrary1
{
[Foo("")]
[Foo(new string(new char[] { }))] // Error 1
[Foo(1.0m)] // Error 1 (no error in ReSharper)
[Foo(new decimal(1.0))] // Error 1
class C
{
static readonly string s1 = "";
static readonly string s2 = new string(new char[] {});
static readonly decimal d1 = 1.0m;
static readonly decimal d2 = new decimal(1.0);
const string constS1 = "";
const string constS2 = new string(new char[] {}); // Error 2
const decimal constD1 = 1.0m;
const decimal constD2 = new decimal(1.0); // Error 2
// Error 1:
// An attribute argument must be a constant expression, typeof expression or
// array creation expression of an attribute parameter type
// Error 2:
// The expression being assigned to (...) must be constant
}
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
class FooAttribute : Attribute
{
public FooAttribute(object obj)
{
if (obj is decimal)
{
// Doomed to be dead code?
}
}
}
}
那么,这是什么东西" 1.0m"其实?我如何解决这个事实,即我不能将它用作属性的参数?我能想到的唯一解决方案是牺牲类型安全性,并在处理自定义属性时执行此操作:
[Bar("1.0")]
class C
{
}
class BarAttribute : Attribute
{
public BarAttribute(string decimalAsString)
{
decimal d = Convert.ToDecimal(decimalAsString);
...
}
}
在处理NUnit' TestCaseAttribute
时,我会做类似的事情。根据{{3}},NUnit会自动转换类型。
[TestCase("1.0")]
public void Test(decimal d)
{
...
}