【问题标题】:Alternative way of checking if an object is a match for any types in a given list检查对象是否与给定列表中的任何类型匹配的替代方法
【发布时间】:2013-12-18 11:25:41
【问题描述】:
if (this.Page is ArticlePage|| this.Page is ArticleListPage)
{
   //Do something fantastic
}

上面的代码可以工作,但考虑到我想将this.Page 与许多不同的类进行比较,我想将这些类存储在一个列表中,然后在列表上执行.Contains()

我将如何实现这一目标?我会以某种方式使用GetType()吗?我可以存储Page 对象的列表,然后以某种方式比较这些类型吗?

注意:您可以假设我比较 this.Page 的所有类都扩展了 Page

【问题讨论】:

  • 你不应该写这种类型的代码。当您发现自己在做这样的事情时,请找到使用多态性的正确方法。多态行为将允许您在不选择类型的情况下选择适当的行为。
  • 一开始有什么更好的方法?谢谢老兄。
  • 您是否会考虑至少创建一个空接口(例如IDoSomethingFantastic),让页面类也实现该接口,那么您的检查将只是if (this.Page is IDoSomethingFantastic)?如果您基本上可以将“神奇”的内容定义/移动到这些页面/界面中,则可以获得额外的奖励。

标签: c# list class inheritance types


【解决方案1】:

此代码将完成这项工作:

HashSet<Type> knownTypes = new HashSet<Type>()
{
    typeof(ArticlePage),
    typeof(ArticleListPage),
    // ... etc.
};

if (knownTypes.Contains(this.Page.GetType())
{
   //Do something fantastic
}

编辑:正如 Chris 所指出的,您可能需要考虑类型继承来完全模仿 is 运算符的行为。这有点慢,但对于某些目的可能更有用:

Type[] knownTypes = new Type[] 
{ 
    typeof(ArticlePage), 
    typeof(ArticleListPage),
    // ... etc.
};

var pageType = this.Page.GetType();
if (knownTypes.Any(x => x.IsAssignableFrom(pageType)))
{
    //Do something fantastic
}

【讨论】:

  • 太好了,+1。看起来很像我所追求的。你为什么使用 HashSet 而不是列表(好奇)?
  • @DeeMac HashSet 在超过 10 个项目时速度更快。
  • 另请注意,这技术上是不一样的行为。使用is 检查的原始代码还检查子类和接口实现。此代码将检查精确匹配类型。这意味着如果你传入ArticlePageArticleListPage 的派生子类,或者你注册了接口,它不会通过。编辑:它可能适合您当前的使用,但如果您决定以其他方式使用它,请在将来注意它。
  • @ChrisSinclair 感谢您指出这一点。如果想要完整的is 等价,则应使用IsAssignableFrom 方法进行类型检查。这有点慢,但在某些情况下可能更有用。
【解决方案2】:

很难评论您的确切用法,但一种(相对)简单的方法可以做到这一点并为您的检查增加一点整洁(尤其是如果您在多个地方执行相同的检查)是定义一个接口,让相关页面实现该接口,然后进行检查。

空界面:

public interface IDoSomethingFantastic
{

}

例如,您的两个页面定义可能如下所示:

public partial class ArticlePage : System.Web.UI.Page, IDoSomethingFantastic
{

}

public partial class ArticleListPage : System.Web.UI.Page, IDoSomethingFantastic
{

}

那么你的支票本质上是:

if (this.Page is IDoSomethingFantastic)
{
    //Do something fantastic
}

这样做的好处是不必集中存储“精彩”页面的列表;相反,您只需在页面类声明中定义它,添加/删除“精彩”页面变得容易。

此外,您也许可以将“出色”的行为移至界面/页面:

public interface IDoSomethingFantastic
{
    void SomethingFantastic();
}

然后在您的检查代码中:

if (this.Page is IDoSomethingFantastic)
{
    ((IDoSomethingFantastic)this.Page).SomethingFantastic();
}

通过这种方式,奇妙事物的实现在其他地方处理,而不是重复。或者您可以将检查和操作完全移至单独的处理类:

if (FantasticHandler.IsPageFantastic(this.Page))
    FantasticHandler.DoSomethingFantastic(this.Page);

【讨论】:

    【解决方案3】:

    虽然你应该重新考虑使用这样的代码(因为它似乎忘记了多态性),你可以使用反射来检查它:

    List<Type> types = new List<Type>() 
    { 
        typeof(ArticlePage), 
        typeof(ArticleListPage) 
    };
    types.Any(type => type.IsAssignableFrom(@object.GetType()));
    

    IsAssignableFrom 不仅适用于特定类,而且适用于其所有子类,就像 is 运算符一样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 2014-07-28
      • 1970-01-01
      • 1970-01-01
      • 2018-04-27
      • 2021-02-06
      • 2019-08-25
      相关资源
      最近更新 更多