user320587
user320587

Reputation: 1367

Generic list of generics

I am having some trouble designing a solution that uses command pattern but with generics. Basically, I have defined a generic interface that has just one method that returns a list of generic object.

public interface IExecute<T>
{
   List<T> Execute();
}

public class SimpleExecute : IExecute<int>
{
   public List<int> Execute()
   { return a list of ints... }
}

public class Main
{
   private List<IExecute<T>> ExecuteTasks; // This is not valid in C#
}

Since generic list of generics isn't valid, I implemented a non-generic interface IExceute and made the generic interface extend the non-generic one and was able to create a list

public interface IExecute {}

public interface IExecute<T> : Execute
{
   List<T> Execute();
}

private List<IExecute> ExecuteTasks;

However, now I am not sure how can I loop through the ExecuteTasks and call the execute method.

I have tried my best to explain the issue. Please, let me know if you need further explanation of my issue.

Thanks

Upvotes: 0

Views: 213

Answers (5)

Christian Rondeau
Christian Rondeau

Reputation: 4603

When you are using generics, consider that IExecute<Class1> is a completely different interface than IExecute<Class2>. In this case, if you were to invoke a common method in both, you'd need another interface; e.g. IExecute.

public interface IExecute<T>
{
    List<T> Execute();
}

public interface IExecute
{
    IList Execute();
}

public class SimpleExecute : IExecute<int>, IExecute
{
    IList IExecute.Execute()
    {
        return Execute();
    }

    public List<int> Execute()
    {
        return new List<int>();
    }
}

Then, to loop you can simply use foreach and/or LINQ.

List<IExecute> entries = new List<IExecute> {new SimpleExecute()};

foreach (var result in entries.Select(x => x.Execute()))
{
}

What you are trying to achieve seems correct because you consider IExecute as a single interface, but in fact it is a "template" for an interface which will be created at compile time.

Upvotes: 0

Silver Solver
Silver Solver

Reputation: 2320

List<IExecute<T>> ExecuteTasks 

is not valid because T is not defined anywhere in the containing class.

Something like this should work instead though:

List<IExecute<Object>> ExecuteTasks;

ExecuteTasks.Add(new SimpleExecute());

Or

public class Main<T>
{
    List<IExecute<T>> ExecuteTasks 
}

Upvotes: 1

phoog
phoog

Reputation: 43046

The best you can do is this:

public interface IExecute { IList Execute(); } 

Then, for example:

public class SimpleExecute : IExecute<int>   
{   
   public List<int> Execute()   
   { return a list of ints... }   
   IList IExecute.Execute() { return this.Execute(); }
}

(Note the explicit interface member implementation for the non-generic IExecute.Execute())

Then:

List<IExecute> iExecuteList = //whatever;
foreach (var ix in iExecuteList)
{
    IList list = ix.Execute();
}

You can't get the specific generic list type at compile time (for example, IList<string>, IList<int>) for the same reason you can't store an int and a string in the same generic list (unless the type argument is object).

Upvotes: 2

HeM01
HeM01

Reputation: 111

public class Main
{
   private List<IExecute<T> ExecuteTasks; // This is not valid in C#
}

There are 2 errors here:

  • T is an unknown class. You should have specified the correct type

  • List< doesn't have a close angle bracket '>'. Each opening bracket must have a closing one. It should look like List<IExecute<T>>

Upvotes: 1

matthewr
matthewr

Reputation: 4739

Try looping through every item by using a foreach loop:

foreach(var item in ExecuteTasks)
{
    item.Execute();
    //...
}

Upvotes: 0

Related Questions