4

to be specific, I want to write an export function which I can use like this:

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

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

I thought about something like the code below, but in this case I have to cast everything to a "List of object" which is not what I want.

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

Can you give me a hint how to solve this elegantly?

Servy
  • 202,030
  • 26
  • 332
  • 449
Jens
  • 505
  • 5
  • 17
  • 2
    Do `HistoryBook` `MathBook` and `ScienceBook` inherit from the same class, say `Book`? – Candide Apr 03 '12 at 06:42
  • 1
    Maybe you want the books to inherit from a `Book` class? – Gene Apr 03 '12 at 06:43
  • 1
    Yes, Make the classes inherit from BaseClass Book or Implement an Interface called Book and then the parameter of the method will be BaseClass Type or Interface Type – Marshal Apr 03 '12 at 06:44
  • Not necessarily. They should all inherit from object, don't they? – Jens Apr 03 '12 at 06:44
  • No, all the classes dont inherit from Class object. It depends on your HistoryBook, MathBook declarations. – Marshal Apr 03 '12 at 06:46
  • For the cause see: [question-about-c-sharp-covariance](http://stackoverflow.com/questions/4034495/question-about-c-sharp-covariance) – nawfal Jun 10 '13 at 17:22
  • Very similiar [can-i-have-a-variable-number-of-generic-parameters](http://stackoverflow.com/questions/1612887/can-i-have-a-variable-number-of-generic-parameters). – nawfal Jun 10 '13 at 17:24

3 Answers3

4
class Book {}

class ScienceBook : Book {}

class MathBook : Book  {}

class ScienceBook : Book {}

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

or you can use interface for it. e.g. interface IBook {}

weeyoung
  • 172
  • 5
  • 1
    Thanks, but they can be different baseclasses. I just want to drop random Lists of stuff into this function and the function uses reflection and the DisplayName-Attribute to output it into an Excel-File. – Jens Apr 03 '12 at 06:47
  • then you can use an interface instead of an inheritance. – weeyoung Apr 03 '12 at 06:48
  • yes. as per below, you may require overloads. you could also create a different wrappers with the interface IBook/IExport . Possibly, have an enum to determine the type for easy conversion. – weeyoung Apr 03 '12 at 07:05
4

If, as you say, you want to be able to pass completely unrelated lists, maybe you should accept the base IList interface:

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

All List<T> objects implement IList, as well as the generic IList<T>, so you can enforce that.

Actually, depending on what you need to do with these lists in the Exporter, perhaps enforcing IEnumerable is enough for you, if all you need is forward-only read-once functionality.

Best way to decide is to determine what the shared functionality you need for all parameters, and define your method signature to enforce that functionality.

UPDATE

Based on your comment, it seems what you want is possible in C# 4.0 using covariant/contravariant generics, meaning that a generic ISomething<out object> could receive an ISomething<string>. The problem is that IList<T> doesn't define a covariant generic parameter, so passing IList<string> for IList<object> doesn't work.

However, IList<T> inherits IEnumerable<out T>, which DOES define a covariant parameter. So if your Export method receives a params IEnumerable<object>[] data parameter, you SHOULD be able to pass it any IList<T> you want.

Avner Shahar-Kashtan
  • 14,492
  • 3
  • 37
  • 63
1
   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)


    }
Marshal
  • 6,551
  • 13
  • 55
  • 91
  • What if I want to export a List - just in case ;-) – Jens Apr 03 '12 at 06:58
  • If the case isn't limited to Generic types, you may not be able to solve this with single method (without much complexity). I think you may need method overloads in that case. – Marshal Apr 03 '12 at 07:02