属性和命名/可选构造函数参数不起作用
我定义了自定义属性,如下所示:
[AttributeUsage(AttributeTargets.Field)]
public class EnumDisplayAttribute : Attribute
{
public string Description { get; private set; }
public string Code { get; private set; }
public EnumDisplayAttribute(string description = null, string code = null)
{
Description = description;
Code = code;
}
}
两个构造函数参数都是可选的。
当在这样的字段上使用此属性时,
public enum TransactionType
{
[EnumDisplay(code: "B")]
Bill,
[EnumDisplay(description: null, code: "C")]
CashReceipt,
}
我在代码编辑器中没有看到任何波浪线,但我看到一个模糊的错误,没有任何列的文件行号。错误信息是:
错误CS0182:属性参数必须是常量表达式,typeof 表达式 或属性参数类型的数组创建表达式
单击错误不会执行任何操作。也就是说,您不会导航到错误站点(显然,因为没有行号和列)。
即使我像这样设置属性:
[EnumDisplay("This is a Bill")]
编译器不喜欢它。
实际上,我被迫提供两个参数(命名或未命名)才能将此属性用作属性。
当然,如果我像这样使用此属性作为常规类:
var enumDisplayAttribute = new EnumDisplayAttribute();
enumDisplayAttribute = new EnumDisplayAttribute(description: "This is a Bill");
enumDisplayAttribute = new EnumDisplayAttribute(code: "B");
enumDisplayAttribute = new EnumDisplayAttribute(description: "This is a Bill", code: "B");
enumDisplayAttribute = new EnumDisplayAttribute("This is a Bill", "B");
enumDisplayAttribute = new EnumDisplayAttribute("This is a Bill");
编译器将接受上述任何一种“样式”。
当然,我错过了一些东西,或者我的大脑无法正常工作。
I have custom attribute defined like so:
[AttributeUsage(AttributeTargets.Field)]
public class EnumDisplayAttribute : Attribute
{
public string Description { get; private set; }
public string Code { get; private set; }
public EnumDisplayAttribute(string description = null, string code = null)
{
Description = description;
Code = code;
}
}
Both constructor parameters are optional.
When using this attribute on a field like so
public enum TransactionType
{
[EnumDisplay(code: "B")]
Bill,
[EnumDisplay(description: null, code: "C")]
CashReceipt,
}
I don't see any squigglies in the code editor but I see a vague error without any File Line number of column. The error message is:
error CS0182: An attribute argument must be a constant expression, typeof expression
or array creation expression of an attribute parameter type
Clicking on the error does nothing. That is, you don't get navigated to the error site (obviously, since there is no line number and column).
even if I set up the attribute like so:
[EnumDisplay("This is a Bill")]
The compiler doesn't like it.
Effectively, I am forced to provide both parameters (named or not) in order to use this attribute as an attribute.
Of course if I use this attribute as a regular class like so:
var enumDisplayAttribute = new EnumDisplayAttribute();
enumDisplayAttribute = new EnumDisplayAttribute(description: "This is a Bill");
enumDisplayAttribute = new EnumDisplayAttribute(code: "B");
enumDisplayAttribute = new EnumDisplayAttribute(description: "This is a Bill", code: "B");
enumDisplayAttribute = new EnumDisplayAttribute("This is a Bill", "B");
enumDisplayAttribute = new EnumDisplayAttribute("This is a Bill");
The compiler will accept any one of the above "styles".
Surely, I'm missing something or my brain is just not working.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在 C# 中已经存在属性的可选值之后,可选参数被添加到 C# 中。因此,对于可选属性参数,您应该回退到特定于属性的语法:
如您所见,最终结果实际上是相同的,但您使用的不是命名参数,而是命名属性(其中语法如
[EnumDisplay(Description = null, Code = "C")]
只能在属性声明中使用)。另一种思考方式是,属性声明从方法/构造函数调用中“借用”了其语法,但属性声明本身并不是方法调用,因此它们无法获得与方法相同的功能。
Optional parameters were added to C# after optional values for attributes already existed in C#. Therefore, for optional attribute parameters, you should fall back to the attribute-specific syntax:
As you see, the end-result is effectively the same, but instead of using named arguments, you are using named properties (where syntax like
[EnumDisplay(Description = null, Code = "C")]
is only possible in attribute declarations).Another way to think of it is that attribute declarations "borrowed" its syntax from method/constructor invocations, but attribute declarations are not in themselves method invocations, so they don't get all the same features as methods.
如果您确实想使用构造函数将值推入属性(例如,如果属性的某些属性是强制性的或对它们执行某种处理),您始终可以使用旧方法并重载构造函数。
例如:
If you do want to push values into your attribute using a constructor (e.g. if some of your attribute's properties are mandatory or to perform some kind of processing on them) you can always go old school and overload the constructor.
For example:
可选参数并不是真正可选的,方法签名中包含所有参数,并且属性是特殊的(存在于可选参数之前,并且在作为属性应用时具有不同的规则(例如,考虑谁调用属性构造函数))。不过我想将来会增加这种支持。
现在,如果您希望实现可选效果,请尝试以下操作:
并按如下方式应用:
Optional parameters are not really optional, the method signature has all arguments in it and attributes are special (existed before optional parameters and have different rules when applied as an attribute (eg consider who calls the attribute constructor)). I imagine however that support will be added in the future.
For now, if you wish to achieve the optional effect try the following:
And apply as so: