如何正确检查一个类/接口是否继承了另一个类/接口?

4
下面的代码正在循环遍历一个字符串字典和IMyCompanySettings,查找实现IMyCompanyProductSetting的值。显然,尝试强制转换并引发异常是一种非常昂贵的方法。
    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;
    }

有更好的方法吗?

5个回答

14

铸造 101 [有关铸造的通用信息]:

使用[对象] is [接口/类]表达式:

if (setting is IMyCompanyProductSetting) {
  ...
}

或者你可以使用 as 关键字,它尝试将对象转换为目标类型,如果失败,则不会抛出异常,而是返回 null。请注意,as 关键字的目标类型必须是引用类型:

var prod = setting as IMyCompanyProductSetting; 

if (prod != null) {
   ...
}

与其使用等效的异常处理,您应该始终使用上述代码。

按类型筛选IEnumerable (使用LINQ):

正如Jon Skeet指出的那样,您应该使用OfType扩展方法轻松地过滤序列(假设您已经拥有了LINQ):

var filteredSequence = sequence.OfType<TargetType>();

IEnumerable 转换为指定类型 (使用 LINQ):

如果你想尝试将每个元素强制转换为目标类型(而不是按类型进行过滤),可以使用 Cast 扩展方法:

var castedSequence = sequence.Cast<TargetType>();

这并不是实现该方法最简单的方式,如果你正在使用.NET 3.5...请看我的答案 :) - Jon Skeet
两个赞和一个采纳,每个单词值15分!(幸好我只需要记忆罐。) - Yes - that Jake.
Jon Skeet,当然。然而,在我看到示例代码中的异常处理时,我认为根本上摆脱它更重要。 - Mehrdad Afshari
哦,这也值得深入探讨一下。我只是想展示一种避免首先编写任何实际代码的方法。 - Jon Skeet

7

“硬”的方法(即LINQ之前)是使用“as”关键字。这比每次使用“is”和强制转换更高效(因为“is”和强制转换都需要执行时检查):

IMyCompanyProductSetting prod = setting as IMyCompanyProductSetting;
if (prod != null)
{
    ret.Add(prod);
}

关于何时使用 "as" 和何时使用强制转换,请参见另一个问题

然而,如果您正在使用 .NET 3.5,则非常容易:

return cfm.Values.OfType<IMyCompanyProductSetting>().ToList();

非常简单 :)

2

Mehrdad已经给出了答案。我只想补充一点,就是你不应该使用“try / catch everything”的技巧。在最好的情况下,你正在尝试捕获一个InvalidCastException。你不会希望忽略其他可能来自你尝试调用的方法执行的异常。


1
你应该使用'Is'语句,以获得更简洁且不容易出错的代码。请参考以下示例。
 if (setting Is IMyCompanyProductSetting)
  ret.add((IMyCompanyProductSetting)setting);

1

要么做

if (setting is IMyCompanyProductSetting)
{
  IMyCompanyProductSetting prod = (IMyCompanyProductSetting)setting;
}

或者

IMyCompanyProductSetting prod = setting as IMyCompanyProductSetting;
if (setting != null)
{
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接