I'm looking at a function with this pattern:
if( obj is SpecificClass1 )
{
((SpecificClass1)obj).SomeMethod1();
}
else if( obj is SpecificClass2 )
{
((SpecificClass2)obj).SomeMethod2();
}
else if( obj is SpecificClass3 )
{
((SpecificClass3)obj).SomeMethod3();
}
and get a code analysis warning: CA1800 Do not cast unnecessarily.
What's a good code pattern I can use to replace this code with that will be performant and concise.
Update
I didn't say, but obj is declared with type object.
I originally asked two questions here. I've split one off (which nobody had yet answered anyway): Why wouldn't the compiler optimize these two casts into one?
The best way would be to introduce an interface that all the types implement. This is only possible if the signatures match (or you don't have too many differences).
If creating an interface is not an option, you can get rid of the CA message by using the following pattern (though this also introduces unnecessary casts and therefore degrades performance a bit):
var specClass1 = obj as SpecificClass1;
var specClass2 = obj as SpecificClass2;
var specClass3 = obj as SpecificClass3;
if(specClass1 != null)
specClass1.SomeMethod1();
else if(specClass2 != null)
specClass2.SomeMethod2();
else if(specClass3 != null)
specClass3.SomeMethod3();
You can also change it to this structure (from my point of view, the above is better in terms of readability):
var specClass1 = obj as SpecificClass1;
if (specClass1 != null)
specClass1.SomeMethod1();
else
{
var specClass2 = obj as SpecificClass2;
if (specClass2 != null)
specClass2.SomeMethod2();
else
{
var specClass3 = obj as SpecificClass3;
if (specClass3 != null)
specClass3.SomeMethod3();
}
}
Also, if you have many types that you want to check for, you can register them in a dictionary and check against the entries of the dictionary:
var methodRegistrations = new Dictionary<Type, Action<object> act>();
methodRegistrations.Add(typeof(SpecificClass1), x => ((SpecificClass1)x).SomeMethod1());
methodRegistrations.Add(typeof(SpecificClass2), x => ((SpecificClass2)x).SomeMethod2());
methodRegistrations.Add(typeof(SpecificClass3), x => ((SpecificClass3)x).SomeMethod3());
var registrationKey = (from x in methodRegistrations.Keys
where x.IsAssignableFrom(obj.GetType()).FirstOrDefault();
if (registrationKey != null)
{
var act = methodRegistrations[registrationKey];
act(obj);
}
Please note that the registrations are easily extendable and that you can also call methods with different arguments in the action.
To avoid the double casting you could do the following
var objClass1= obj as SpecificClass1;
if(objClass1!=null)
objClass1.SomeMethod1();
Regarding the pattern you could make all these classes implement a common interface and make your method receive the interface.
public void SomeMethod(ISpecificInterface specific)
{
specific.SomeMethod1();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With