我有自定义的自定义属性:
[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");
编译器将接受上述任何一种“样式”。
当然,我遗失了一些东西,或者我的大脑不能正常工作。
答案 0 :(得分:28)
在C#中已存在的属性的可选值之后,可选参数被添加到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")]
之类的语法只能在属性声明中使用)。
另一种思考方式是属性声明从方法/构造函数调用“借用”其语法,但属性声明本身不是 方法调用,因此它们不会完全相同作为方法的特征。
答案 1 :(得分:5)
如果您确实想使用构造函数将值推送到属性中(例如,如果某些属性的属性是必需的,或者对它们执行某种处理),您可以随时上学并重载构造函数。
例如:
[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;
}
}
答案 2 :(得分:3)
可选参数实际上不是可选的,方法签名中包含所有参数,属性是特殊的(存在于可选参数之前,并且当作为属性应用时具有不同的规则(例如,考虑谁调用属性构造函数))。但我想,将来会增加支持。
目前,如果您希望达到可选效果,请尝试以下操作:
[AttributeUsage(AttributeTargets.Field)]
public class EnumDisplayAttribute : Attribute
{
public string Description { get; set; }
public string Code { get; set; }
}
并按原样申请:
[EnumDisplay(Description = null, Code = "C")]
private object _aField;