Reputation: 3305
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.
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.
Upvotes: 2
Views: 258
Reputation: 3305
The way I resolved this code was by moving the overloads to a new abstract class with separate methods instead of the the original constructors:
public CustomRangeValidationStringAttribute(string value) {}
public CustomRangeValidationGenericAttribute(object value) {}
In the two classes inheriting from this new base class each use their own method, creating two different attributes to choose from, [CustomRangeValidationString] and [CustomRangeValidationGeneric].
Upvotes: 0
Reputation: 3775
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.
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.
Upvotes: 2
Reputation: 239646
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.
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.
Upvotes: 3
Reputation: 1
You could use a generic class.
class YourClass<T>
{
public YourClass(T value){}
}
Upvotes: -1