具有字符串参数的构造函数和具有对象参数的相同重载

Constructor with string parameter and identical overload with object parameter

我的class目前有两个构造函数,是重载:

public CustomRangeValidationAttribute(string value) {}

public CustomRangeValidationAttribute(object value) {}

这似乎工作正常:当我使用 string 调用方法时,第一个构造函数被调用,当我使用不同的值时,例如 integerboolean ,第二个构造函数被调用。

我假设有一个规则强制特定类型匹配到更具体的重载中,防止

var c = new CustomRangeValidationAttrubute("test");

来自调用对象重载。

这是"safe code",还是应该(或可以)改进代码?我有一种挥之不去的感觉,这不是最佳做法。

您可以使用通用 class。

See the documentation

class YourClass<T> 
{
    public YourClass(T value){}
}

一旦有带有更多派生类型签名的重载,编译器将始终选择您提供的最具体的类型。

话虽这么说,除非有人 new CustomRangeValidationAttrubute((object)"test") 如果您将字符串传递给 CustomRangeValidationAttrubute,则始终会选择参数为 string 的构造函数。

关于这是否是不好的做法,如果我没有看到您的具体用例,我无法确定,请记住您传递给 new CustomRangeValidationAttrubute(object) 的每个值类型都将被装箱,并且这个不好,因为它会给 GC 带来压力,而且你会失去类型安全。

您有两个重载,它们仅在引用类型上有所不同,并且引用类型之间存在层次关系,因此一个可以强制转换为另一个。

In such a circumstance, you really ought to make sure that the code behaves the same logically when the broader overload is selected but the reference turns out to be of the more derived输入1,2 是您集中注意力的地方。当然,如果您能坚持这条规则,通常会发现不需要派生更多的重载,并且可以在更广泛的方法中 进行特殊处理。


1特别是因为,正如 vc74 在评论中指出的那样,重载决议(通常忽略 dynamic)是在编译时根据编译时类型完成的3.

2这符合重载的相同广泛原则。不要重载 选择哪个 会导致逻辑上不同的结果。如果你表现出不同的行为,不要给它们相同的名字(对于构造函数,这可能意味着分成两个单独的 classes,可能有一个共享的基础 class,如果这是你想要的做)

3我很欣赏这是针对属性的,因此您希望只有编译时相关,但我仍然坚持这里的一般原则,在可能的情况下。

我解决此代码的方法是将重载移动到一个新的抽象 class 中,使用单独的方法而不是原始构造函数:

public CustomRangeValidationStringAttribute(string value) {}

public CustomRangeValidationGenericAttribute(object value) {}

在从这个新基础 class 继承的两个 class 中,每个都使用自己的方法,创建两个不同的属性以供选择,[CustomRangeValidationString] 和 [CustomRangeValidationGeneric]。