Constructor with string parameter and identical overload with object parameter

The name of the picture


Constructor with string parameter and identical overload with object parameter



My class currently has two constructors, which are overloads:


public CustomRangeValidationAttribute(string value) {}



and


public CustomRangeValidationAttribute(object value) {}



this appears to be working correctly: When I call the method using a string the first constructor is called, when I use different values, for example an integer or boolean, the second constructor is called.


string


integer


boolean



I assume there is a rule to force specific type matches into the more specific overload, preventing


var c = new CustomRangeValidationAttrubute("test");



from calling the object-overload.



Is this "safe code", or should (or can) the code be improved? I have a nagging feeling this is not the best practice.





Depends, what you are trying to achieve?
– kuskmen
5 hours ago







I need to be sure there are absolutely no risks of the wrong constructor getting called. And if that's not the case, it still feels like a bad practice somehow.
– MeanGreen
5 hours ago





If the object based method will do something fundamentally different/wrong if it happens to be called with a string, that's probably a logical error in creating overloads in the first place, but nothing to do with the calling code.
– Damien_The_Unbeliever
5 hours ago


object


string





Just keep in mind that the overload will be selected at compile time so if you have an object reference which is actually a string, the 2nd overload will be called (unless you cast the object to a string).
– vc 74
5 hours ago





@mjwills - difficult to do with constructors, since you can't run logic before chaining (in C#)
– Damien_The_Unbeliever
4 hours ago




3 Answers
3



You have two overloads which only vary in the reference types and there's a hierarchical relationship between the reference types, such that one may be cast to the other.



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 type1,2. That is where to focus your attention. Of course, if you can stick by this rule, often it'll turn out that the more derived overload isn't required and can just be special-cased within the broader method.



1Especially because, as vc74 points out in a comment, overload resolution (generally, ignoring dynamic) is done at compile time based on compile-time types3.


dynamic



2And this fits the same broad principal for overloads. Don't have overloads where which one is selected leads to logically different results. If you're exhibiting different behaviours, don't give them the same name (for constructors, that may mean splitting into two separate classes, possibly with a shared base class, if that's what you intend to do)



3I appreciate that this is for an attribute and so you're expecting only compile-time to be relevant, but I'd still hew to the general principal here, where possible.



Once there is overload with signature of more derived type the compiler will always choose most concrete type you provide.



That being said, unless someone does new CustomRangeValidationAttrubute((object)"test") if you pass string to CustomRangeValidationAttrubute always constructor with string in it's parameter will be chosen.


new CustomRangeValidationAttrubute((object)"test")


CustomRangeValidationAttrubute


string



About if this is bad practice, I can't tell for sure if I don't see your specific use case, just keep in mind every value type you pass to new CustomRangeValidationAttrubute(object) will be boxed and this is bad as it puts pressure to the GC and whats more you will loose type safety.


new CustomRangeValidationAttrubute(object)



You could use a generic class.



See the documentation


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





Thought I didn't state it explicitly, my class is an attribute, inheriting from RemoteAttribute and unfortunately generics are not allowed in attribute classes.
– MeanGreen
5 hours ago






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Stripe::AuthenticationError No API key provided. Set your API key using “Stripe.api_key = ”

CRM reporting Extension - SSRS instance is blank

Keycloak server returning user_not_found error when user is already imported with LDAP