【问题标题】:Passing a variable number of generic type parameters传递可变数量的泛型类型参数
【发布时间】:2012-04-03 06:40:48
【问题描述】:

具体来说,我想写一个导出函数,我可以这样使用:

List<HistoryBook> HistoryBooks = something;
List<MathBook> MathBooks = something;
List<ScienceBook> ScienceBooks = something;

ExcelExporter.Export(FileName, HistoryBooks, MathBooks, ScienceBooks);

我想过类似下面的代码,但在这种情况下,我必须将所有内容都转换为“对象列表”,这不是我想要的。

public void Export(string FileName, params List<object>[] Data)

你能告诉我如何优雅地解决这个问题吗?

【问题讨论】:

  • HistoryBook MathBookScienceBook 是否继承自同一个类,比如 Book
  • 也许您希望书籍继承自 Book 类?
  • 是的,让类继承BaseClass Book或者实现一个叫Book的接口,然后方法的参数就是BaseClass类型或者接口类型
  • 不一定。它们都应该从对象继承,不是吗?
  • 不,所有的类都不是继承自 Class 对象。这取决于您的 HistoryBook、MathBook 声明。

标签: c# generics params contravariance covariant


【解决方案1】:

如你所说,如果你希望能够传递完全不相关的列表,也许你应该接受基本的 IList 接口:

public void Export(string FileName, params IList[] Data)

所有List&lt;T&gt; 对象都实现IList,以及通用IList&lt;T&gt;,因此您可以强制执行。

实际上,根据您需要在导出器中对这些列表执行的操作,如果您只需要只转发一次的只读功能,那么强制执行 IEnumerable 可能就足够了。

最好的决定方法是确定所有参数所需的共享功能,并定义方法签名以强制执行该功能。

更新

根据您的评论,您想要的似乎在 C# 4.0 中使用协变/逆变泛型是可能的,这意味着泛型 ISomething&lt;out object&gt; 可以接收 ISomething&lt;string&gt;。问题是IList&lt;T&gt; 没有定义协变泛型参数,因此将IList&lt;string&gt; 传递给IList&lt;object&gt; 不起作用。

但是,IList&lt;T&gt; 继承了IEnumerable&lt;out T&gt;,它确实定义了一个协变参数。因此,如果您的 Export 方法接收到 params IEnumerable&lt;object&gt;[] data 参数,您应该能够将其传递给您想要的任何 IList&lt;T&gt;

【讨论】:

  • 这是我想要的方向。但。我想 - 不知何故 - 确保 IList 中的每个项目都是相同的类型。这就是为什么我想通过使用泛型类型列表来确保它。
  • 我认为用解决方案更新了我的答案。
  • 非常感谢!帮了我很多!
【解决方案2】:
class Book {}

class ScienceBook : Book {}

class MathBook : Book  {}

class ScienceBook : Book {}

public void Export(string FileName, IList<Book> Data)

或者你可以使用它的接口。 例如 界面 IBook {}

【讨论】:

  • 谢谢,但它们可以是不同的基类。我只想将随机的东西列表放入此函数中,并且该函数使用反射和 DisplayName-Attribute 将其输出到 Excel 文件中。
  • 那么你可以使用接口而不是继承。
  • 是的。如下所示,您可能需要重载。您还可以使用 IBook/IExport 接口创建不同的包装器。可能,有一个枚举来确定类型以便于转换。
【解决方案3】:
   public interface IBook {}

   public class ScienceBook : IBook {} 
   public class MathBook: IBook {}
   public class HistoryBook: IBook {}

    class Main()
    {
      List<IBook> hbook = new List<HistoryBook>();
      List<IBook> mbook = new List<MathBook>();
      List<IBook> sbook = new List<ScienceBook> ();

      public void Export(string FileName, List<IBook> Data)


    }

【讨论】:

  • 如果我想导出 List 怎么办 - 以防万一 ;-)
  • 如果情况不限于通用类型,您可能无法用单一方法解决这个问题(没有太多复杂性)。我认为在这种情况下您可能需要方法重载。
猜你喜欢
  • 2021-06-17
  • 1970-01-01
  • 1970-01-01
  • 2019-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-27
  • 2016-09-14
相关资源
最近更新 更多