具有字符串参数的构造函数和具有对象参数的相同重载
Constructor with string parameter and identical overload with object parameter
我的class目前有两个构造函数,是重载:
public CustomRangeValidationAttribute(string value) {}
和
public CustomRangeValidationAttribute(object value) {}
这似乎工作正常:当我使用 string
调用方法时,第一个构造函数被调用,当我使用不同的值时,例如 integer
或 boolean
,第二个构造函数被调用。
我假设有一个规则强制特定类型匹配到更具体的重载中,防止
var c = new CustomRangeValidationAttrubute("test");
来自调用对象重载。
这是"safe code",还是应该(或可以)改进代码?我有一种挥之不去的感觉,这不是最佳做法。
您可以使用通用 class。
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]。
我的class目前有两个构造函数,是重载:
public CustomRangeValidationAttribute(string value) {}
和
public CustomRangeValidationAttribute(object value) {}
这似乎工作正常:当我使用 string
调用方法时,第一个构造函数被调用,当我使用不同的值时,例如 integer
或 boolean
,第二个构造函数被调用。
我假设有一个规则强制特定类型匹配到更具体的重载中,防止
var c = new CustomRangeValidationAttrubute("test");
来自调用对象重载。
这是"safe code",还是应该(或可以)改进代码?我有一种挥之不去的感觉,这不是最佳做法。
您可以使用通用 class。
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]。