Reputation: 17121
The code below is looping through a dictionary of strings and IMyCompanySettings looking for values that implement IMyCompanyProductSetting. Clearly, trying to cast and raising an exception is a very expensive way to do this.
public static List<IMyCompanyProductSetting> GetProductSettings(ConfigurationManager cfm)
{
List<IMyCompanyProductSetting> ret = new List<IMyCompanyProductSetting>();
foreach(IMyCompanySetting setting in cfm.Values)
{
try
{
IMyCompanyProductSetting prod = (IMyCompanyProductSetting)setting;
ret.Add(prod);
}
catch
{
// Do nothing.
}
}
return ret;
}
What's a better way to do this?
Upvotes: 4
Views: 3877
Reputation: 421968
Use [object] is [interface/class]
expression:
if (setting is IMyCompanyProductSetting) {
...
}
Alternatively you can use the as
keyword which tries to cast the object and if it fails, instead of throwing exception, it'll return null
. Note that the target type must be a reference type in the as
keyword:
var prod = setting as IMyCompanyProductSetting;
if (prod != null) {
...
}
You should always use the above code instead of the equivalent exception handling.
IEnumerable
by type (LINQy):As Jon Skeet pointed out, you should use OfType
extension method to filter a sequence easily (assuming you got LINQ):
var filteredSequence = sequence.OfType<TargetType>();
IEnumerable
to type (LINQy):If you want to try casting each element to the target type (as opposed to filtering by type), you can use the Cast
extension method:
var castedSequence = sequence.Cast<TargetType>();
Upvotes: 14
Reputation: 273169
Either do
if (setting is IMyCompanyProductSetting)
{
IMyCompanyProductSetting prod = (IMyCompanyProductSetting)setting;
}
or
IMyCompanyProductSetting prod = setting as IMyCompanyProductSetting;
if (setting != null)
{
}
Upvotes: 1
Reputation: 12796
You should use the 'Is' statement instead for more concise and less error prone code. See the example below.
if (setting Is IMyCompanyProductSetting)
ret.add((IMyCompanyProductSetting)setting);
Upvotes: 1
Reputation: 161773
Mehrdad has the answer. I'll only add that you should never use that "try / catch everything" trick. At best in that case, you're trying to catch an InvalidCastException. You wouldn't want to ignore some other exception, possibly from the execution of the method you're trying to call.
Upvotes: 2
Reputation: 1499770
The "hard" way (pre-LINQ) is to use "as". This is more efficient than using "is" and then casting each time (as both the "is" and the cast require execution-time checks):
IMyCompanyProductSetting prod = setting as IMyCompanyProductSetting;
if (prod != null)
{
ret.Add(prod);
}
See another question for when to use "as" and when to use a cast.
If you're using .NET 3.5, however, it's really easy:
return cfm.Values.OfType<IMyCompanyProductSetting>().ToList();
Very easy :)
Upvotes: 7