从类/接口检查继承的正确方法是什么?

时间:2009-04-02 22:37:13

标签: c# .net reflection inheritance

下面的代码循环遍历字符串字典, 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 个答案:

答案 0 :(得分:14)

铸造101 [关于铸造材料的一般信息]:

使用[object] is [interface/class]表达式:

if (setting is IMyCompanyProductSetting) {
  ...
}

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

var prod = setting as IMyCompanyProductSetting; 

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

您应始终使用上述代码而不是等效的异常处理。

按类型过滤IEnumerable(LINQy):

正如Jon Skeet指出的那样,你应该使用OfType扩展方法轻松过滤序列(假设你得到了LINQ):

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

IEnumerable转换为类型(LINQy):

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

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

答案 1 :(得分:7)

“硬”方式(LINQ之前)是使用“as”。这比使用“is”然后每次转换(因为“是”和转换需要执行时间检查)更有效:

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

有关何时使用“as”以及何时使用演员表,请参阅another question

但是,如果您使用的是.NET 3.5,则非常简单:

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

非常简单:)

答案 2 :(得分:2)

Mehrdad有答案。我只会补充一点,你永远不应该使用“尝试/捕捉一切”技巧。在这种情况下,最好是尝试捕获InvalidCastException。您不希望忽略其他一些异常,可能来自您尝试调用的方法的执行。

答案 3 :(得分:1)

您应该使用'Is'语句来获得更简洁,更不容易出错的代码。请参阅下面的示例。

 if (setting Is IMyCompanyProductSetting)
  ret.add((IMyCompanyProductSetting)setting);

答案 4 :(得分:1)

要么

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

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