何时使用泛型和类型检查?

tou*_*ody 1 c# generics reflection

假定A通过Z将26类我所定义.在以下示例中:

  private List<A> _listA;
  private List<B> _listB;
  // private List<C>, and so on, through...
  private List<Z> _listZ;

  private void setLabelA()
  {
      LabelA.Text = _listA.Count;
  }

  // private void setLabelB() exists
  // and so does setLabelC()
  // and so on, all the way through to...

  private void setLabelZ()
  {
      LabelA.Text = _listZ.Count;
  }
Run Code Online (Sandbox Code Playgroud)

在我看来除了以下之外没有办法缩短这个:

  private void setLabel<genericType>(List<genericType> list)
  {
      if(list is List<A>)      LabelA.Text = _listA.Count;
      else if(list is List<B>) LabelB.Text = _listB.Count;
      else if(list is List<C>) LabelC.Text = _listC.Count;
      //  and so on...
      else if(list is List<Z>) LabelZ.Text = _listZ.Count;
  }
Run Code Online (Sandbox Code Playgroud)

重载函数名称不会减少代码行数:

  private void setLabel(List<A> list)
  {
      LabelA.Text = _listA.Count;
  }

  private void setLabel(List<B> list)
  {
      LabelB.Text = _listB.Count;
  }
Run Code Online (Sandbox Code Playgroud)

我更喜欢使用is运算符来确定Label要设置的位置,因为它保留了空间(在这种情况下,50行无意义括号和25行略有不同的函数名称). 但是,Stack Overflow用户建议我使用泛型,而是使用单独的函数,每个函数一个Label.虽然这个解决方案可行,但我宁愿不这样做.

对于使用is运算符以及明确键入我的函数有什么好处吗?

Ser*_*rvy 5

好处是您的类型检查是静态的,而不是动态的.如果有人传入List<SomeRandomeClassYouDontSupport>第一个方法,那么代码将编译并且在运行时无法正常工作.它要么什么也不做,抛出异常,或者你要编写的任何代码,但重点是调用者在运行代码之前不会看到他们做错.

当您有多个重载时,验证将在编译时完成.如果提供了不受支持的类型,则代码甚至不会编译而不是编译而不起作用.

这也是一个重要的语义差异.泛型可以说," 无论类型是什么,这种方法都会起作用".创建列表时,没有提供正确和错误的类型参数.您可以创建所需类型的列表.这是对泛型的适当使用,因为列表是概念上通用的数据结构.有几个重载是一种说法,"支持这种有限的类型列表." 你处于后一种情况,因此这使得调用者的行为更加清晰,因此他们只需查看其签名就能理解该方法需要做什么.

说完这一切之后,看起来这甚至都不是你应该做的事情.如果你真的想让一个方法接受编译时已知的有限数量类型之一作为参数,那么重载是正确的方法,但在你的情况下,你根本不应该做任何这样的事情.您应该将这些UI组件绑定到此注释中提到的视图.