Petew
Petew

Reputation: 150

Generic class with dynamic number of types

I don't know how to phrase this question without using an example, so here we go...

I have defined a class like this:

public class Orchestration<T1, T2, T3>
{

With this constructor:

public Orchestration(Action<T1, T2, T3> action, int maxNumberOfRetries)

And a method called Run:

public bool Run(T1 one, T2 two, T3 three)

Now, if I do this:

var orchestration = new Orchestration<string, string, bool>(File.Copy, 5);
orchestration.Run("c:\filename.txt", "d:\filename.txt", true)

then the orchestration will try to run File.Copy 5 times before it return false, meaning the job has failed (the background here is that I was trying to rescue som files from a disk that only worked now and then)

The Orchestration class is generic and I can use it to run any method that has three parameters.

My question is this: Can I define the Orchestration-class in a manner that the number of parameters does not need to be determined in advance?

My goal then would be to enable it to run any method, not only methods that takes three parameters...

Upvotes: 6

Views: 2667

Answers (3)

Clever Neologism
Clever Neologism

Reputation: 1332

No, you cannot do that.

Take a look at Tuples, Actions and Funcs in the .NET API... they have to create a version of each of those generic classes that takes 1 type arguments, one that takes 2 type arguments, etc. etc.

If you want something cool, try this:

static class Extensions {

  public static TimesDo( this int x, Action action) {
      for (int i = 0; i < x; i++) action.Invoke();   
  }
} 

Then:

int x = 4; x.TimesDo(() => { File.Copy( .... ) } );

or

(5).TimesDo(() => { File.Copy( .... ) });

Upvotes: 0

Servy
Servy

Reputation: 203802

Just have it accept an Action and close over whatever parameters you would have for your actual method:

public Orchestration(Action action, int maxNumberOfRetries)

var orchestration = new Orchestration(
    () => File.Copy("c:\filename.txt", "d:\filename.txt", true), 5);

It means knowing the parameter values on construction, rather than when calling Run, but in this context that doesn't seem like it should be a problem you can't resolve.

Upvotes: 7

Reed Copsey
Reed Copsey

Reputation: 564333

There is not a way to do this with generics in C#. This would require something similar to variadic templates in C++, but there is no equivelent in the managed world. That's why classes such as Tuple have so many different classes with the factory methods to create the various versions.

If your parameters were either non-generic (ie: object) or always string, you could use params to allow a variable number of arguments.

Upvotes: 10

Related Questions