我的课目前有两个构造函数,它们是重载:
public CustomRangeValidationAttribute(string value) {}
和
public CustomRangeValidationAttribute(object value) {}
这似乎正常工作:当我使用string
调用方法时,将调用第一个构造函数,而当我使用不同的值(例如integer
或boolean
)时,第二个构造函数被调用。
我假设有一个规则将特定类型的匹配强制为更特定的重载,以防止
var c = new CustomRangeValidationAttrubute("test");
通过调用对象重载。
这是“安全代码”,还是应该(或可以)改进代码?我觉得这不是最佳做法。
答案 0 :(得分:2)
一旦带有更多派生类型的签名的重载,编译器将始终选择您提供的最具体的类型。
话虽这么说,除非有人将new CustomRangeValidationAttrubute((object)"test")
传递给CustomRangeValidationAttrubute
,否则总是选择参数为string
的构造函数。
关于这是否是不好的做法,我无法确定我是否看不到您的特定用例,请记住,您传递给new CustomRangeValidationAttrubute(object)
的每个值类型都将被装箱,这是不好的因为这会给GC带来压力,而且您将失去类型安全性。
答案 1 :(得分:2)
您有两个重载,它们仅在引用类型方面有所不同,并且引用类型之间存在层次关系,因此可以将其中一个强制转换为另一种。
在这种情况下,您确实应该确保在选择了更广泛的重载但引用却属于派生类型后,代码在逻辑上表现出相同的行为。 1 ,2 。 那是您集中注意力的地方。当然,如果您遵守此规则,通常会发现不需要更多派生的重载,而可以在更广泛的方法中 进行特殊情况设置。
1 尤其是,正如vc74在注释中指出的那样,重载解析(通常忽略dynamic
)是在编译时根据编译时类型进行的 3 < / sup>。
2 这与重载的原理相同。选择被选中的不会导致逻辑上不同的结果,因此不要有重载。如果您表现出不同的行为,请不要给它们使用相同的名称(对于构造函数,这可能意味着分成两个单独的类,如果您打算这样做,则可能使用共享的基类)
3 我很高兴这是针对属性的,因此您希望仅编译时才有意义,但在可能的情况下,我仍会参考此处的一般原则。
答案 2 :(得分:0)
我解析此代码的方式是将重载移动到具有单独方法而不是原始构造函数的新抽象类:
public CustomRangeValidationStringAttribute(string value) {}
public CustomRangeValidationGenericAttribute(object value) {}
在继承自这个新基类的两个类中,每个类都使用各自的方法,它们创建了两个不同的属性可供选择:[CustomRangeValidationString]和[CustomRangeValidationGeneric]。
答案 3 :(得分:-1)