这个东西“1.0m”究竟是什么?我怎么能解决不能将它用作属性参数的问题?

时间:2014-07-25 11:37:48

标签: c# annotations decimal const custom-attributes

我很困惑,因为在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)
{
    ...
}

0 个答案:

没有答案