简体   繁体   English

通过将默认字符串参数传递给属性导致的C#编译器错误

[英]C# Compiler error caused by passing default string parameter to attribute

Why does the code below give me the exception: 为什么下面的代码给我例外:

CSC error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type CSC错误CS0182:属性参数必须是属性参数类型的常量表达式,typeof表达式或数组创建表达式

On my build server? 在我的构建服务器上?

/// Customer.cs...

[Search(SearchAttribute.SearchDisplay.Regular)] 
public Category Category
{
     get; set;
}

public enum Category : byte
{
    X = 0x01,
    Y = 0x02,
    ...
}

/// SearchAttribute.cs...

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class SearchAttribute : Attribute
{
    public SearchDisplay Display { get; private set; }

    public enum SearchDisplay
    {
        None = (byte) 0x01,
        Regular = (byte) 0x02
    }

    public SearchAttribute(SearchDisplay display, string columnName = null)
        : base()
    {
        Display = display;
    }
}

Many Thanks. 非常感谢。

Infuriatingly, it builds fine in VS2012. 令人愤怒的是,它在VS2012中可以正常运行。 I'm unsure what version of the compiler runs on the server - but I'm fairly sure it's not the 2012 one. 我不确定服务器上运行的是哪个版本的编译器-但我很确定它不是2012版本。

UPDATE UPDATE

Thanks to the answerers below I've figured this out: 感谢下面的回答者,我已经弄清楚了:

I am using VS2012, but the build server is still using the VS2010 build process. 我正在使用VS2012,但是构建服务器仍在使用VS2010构建过程。 There is a bug in the VS2010 / C#4 compiler that occurs when a null valued default parameter is used in an attribute. 在属性中使用空值默认参数时,VS2010 / C#4编译器中会出现一个错误 I can get around this 3 ways: 我可以通过以下三种方法解决:

  1. Don't use a default parameter - public SearchAttribute(SearchDisplay display, string columnName) 不要使用默认参数- public SearchAttribute(SearchDisplay display, string columnName)
  2. Use a empty string - public SearchAttribute(SearchDisplay display, string columnName = "") 使用空字符串-公共SearchAttribute(SearchDisplay显示,字符串columnName =“”)
  3. Update my build server. 更新我的构建服务器。

I am going with 2 just now. 我现在要和2一起去。 3 is something that I will need to think about at another time. 3是我以后需要考虑的问题。

I think the Customer.cs file is in a separate assembly (C# project), and that assembly references the assembly (project) in which SearchAttribute.cs is located. 我认为Customer.cs文件位于单独的程序集(C#项目)中,并且该程序集引用SearchAttribute.cs所在的程序集(项目)。

For the enum SearchDisplay and the optional parameter columnName in the constructor to work correctly, it is then vital that both assemblies are recompiled in the correct order. 为了使构造函数中的枚举SearchDisplay和可选参数columnName能够正常工作,至关重要的是, 两个程序集必须以正确的顺序重新编译。 I suspect that wasn't the case on your build server. 我怀疑构建服务器上的情况并非如此。 The dependent assembly was probably compiled with a reference to an old version of the assembly where SearchAttribute is located. 依赖程序集可能是通过引用SearchAttribute所在程序集的旧版本进行编译的。

UPDATE UPDATE

See all the linked threads on the right. 查看右侧所有链接的线程。 This is a bug that they say is fixed with Visual Studio 2012 (C# 5 compiler). 他们说这是Visual Studio 2012(C#5编译器)已修复的错误。 It happens only when the default value of the optional parameter is null . 仅当可选参数的默认值为null时,它才会发生。 In my first test I made the silly decision to use another string (which would be recognizable), but it doesn't happen with another string. 在我的第一个测试中,我做出了使用另一个字符串(可以识别)的愚蠢决定,但是对于另一个字符串却没有发生。 (Will erase my comment below.) (将在下面删除我的评论。)

When the usage of the attribute is in the same assembly as the the attribute class itself, it helps to give the null literal an explicit type, as in: 当属性的用法与属性类本身在同一程序集中时,这有助于为null文字提供显式类型,例如:

public SearchAttribute(SearchDisplay display, string columnName = (string)null)
...

With this, it seems to work as long as all usages are in the same assembly as the above construtor. 这样,只要所有用法与上述构造函数都在同一程序集中,就可以正常工作。 However, in your case they are in different assemblies. 但是,在您的情况下,它们位于不同的程序集中。

Problem goes away if you are willing to use the empty string instead: 如果您愿意使用空字符串代替,问题就解决了:

public SearchAttribute(SearchDisplay display, string columnName = "")
...

Otherwise, I suggest you use the old pre-C#-4-style 否则,建议您使用旧的C#-4-以前的样式

[Search(SearchAttribute.SearchDisplay.Regular)] 
public Category Category
...

[Search(SearchAttribute.SearchDisplay.Regular, ColumnName = "Changed!")] 
public Category AnotherCategory
...

This works with no columnName parameter in the constructor, as long as there's a class member (instance property or field) called ColumnName . 只要有一个名为ColumnName的类成员(实例属性或字段),此构造函数在构造函数中就不会使用columnName参数。 That ColumnName must not be read-only or get-only. ColumnName不得为只读或仅获取。

你不是说

 [Search(SearchAttribute.SearchDisplay.Regular)] 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM