属性和命名/可选构造函数参数不起作用
本文关键字:构造函数 参数 不起作用 属性 | 更新日期: 2023-09-27 18:15:13
我已经定义了自定义属性:
[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");
编译器将接受上述任何一种"样式"。
肯定是我漏了什么,或者是我的脑子坏了。
在c#中已经存在的属性的可选值之后添加了可选参数。因此,对于可选的属性参数,您应该退回到特定于属性的语法:
[AttributeUsage(AttributeTargets.Field)]
public class EnumDisplayAttribute : Attribute
{
public string Description { get; set; }
public string Code { get; set; }
public EnumDisplayAttribute()
{
}
}
public enum TransactionType
{
[EnumDisplay(Code = "B")]
Bill,
[EnumDisplay(Description = null, Code = "C")]
CashReceipt,
}
正如您所看到的,最终结果实际上是相同的,但是您使用的不是命名参数,而是命名属性(其中像[EnumDisplay(Description = null, Code = "C")]
这样的语法只可能在属性声明中)。
另一种思考方式是,属性声明从方法/构造函数调用中"借用"了它的语法,但属性声明本身并不是方法调用中的,因此它们不能获得与方法相同的所有特性。
如果你确实想使用构造函数将值推入属性(例如,如果你的属性的某些属性是强制性的,或者对它们执行某种处理),你可以使用老式方法重载构造函数。
例如:[AttributeUsage(AttributeTargets.Field)]
public class SampleAttribute : Attribute
{
public string MandatoryProperty { get; private set; }
public string OptionalProperty { get; private set; }
// we use an overload here instead of optional parameters because
// C# does not currently support optional constructor parameters in attributes
public SampleAttribute(string mandatoryProperty)
: this(mandatoryProperty, null)
{
}
public SampleAttribute(string mandatoryProperty, string optionalProperty)
{
MandatoryProperty = mandatoryProperty;
OptionalProperty = optionalProperty;
}
}
可选参数并不是真正的可选,方法签名中包含了所有的参数,并且属性是特殊的(存在于可选参数之前,并且在作为属性应用时具有不同的规则(例如考虑谁调用属性构造函数))。但是,我想将来会增加这种支持。
目前,如果您希望实现可选效果,请尝试以下操作:
[AttributeUsage(AttributeTargets.Field)]
public class EnumDisplayAttribute : Attribute
{
public string Description { get; set; }
public string Code { get; set; }
}
和apply as so:
[EnumDisplay(Description = null, Code = "C")]
private object _aField;