0

Is there a way to call a generic function in a foreach loop for Types known at compile time? This code wont compile, because type is not a valid parameter for DoSmth, but illustrates what I want to do.

    public class X { }

    public class Y { }

    public class Z { }

    public class Example
    {
        public Example()
        {
            Types = new List<Type>
            {
                typeof(X),
                typeof(Y),
                typeof(Z)
            };
        }

        private List<Type> Types { get; }

        public void DoAllTypes()
        {
            foreach (var type in Types)
            {
                DoSmth<type>();
            }
        }

        private void DoSmth<T>()
        {
            // ... do smth based on T
        }
    }

Edit: Why is the question a duplicate? I specifically stated "known at compile time". The other uses Reflections to get the types not known at compile time.

  • 2
    If you want a method that accept only a type parameter to do something based on that type, the simplest way to do it would be to write `DoSmth` like this: `private void DoSmth(Type type)`... – Zohar Peled Nov 29 '17 at 06:55
  • Seems as you actually need *three* methods, one for every type. As all those types doesn´t seem to have anything in common, there´s not much you can do within a common method. – MakePeaceGreatAgain Nov 29 '17 at 07:13

2 Answers2

4

You can save delegates (Action) to your methods:

public class Example
{
    public Example()
    {
        Types = new List<Action>
        {
            DoSmth<X>,
            DoSmth<Y>,
            DoSmth<Z>
        };
    }

    private List<Action> Types { get; }

    public void DoAllTypes()
    {
        foreach (var type in Types)
        {
            type();
        }
    }

    private void DoSmth<T>()
    {
        // ... do smth based on T
    }
}

Better way - use inheritance:

public class A
{
    public virtual void DoSmth()
    {
    }
}

public class X : A
{
    public override void DoSmth()
    {

    }
}

public class Y : A
{
    public override void DoSmth()
    {

    }
}

public class Z : A
{
    public override void DoSmth()
    {

    }
}

public class Example
{
    public Example()
    {
        Types = new List<A>
        {
            new X(),
            new Y(),
            new Z()
        };
    }

    private List<A> Types { get; }

    public void DoAllTypes()
    {
        foreach (var type in Types)
        {
            type.DoSmth();
        }
    }
}
Backs
  • 24,430
  • 5
  • 58
  • 85
1

Do you really have any use of generic in this case? Here's an example how you can solve it with switch statements with pattern.

public void DoAllTypes()
{
    foreach (var type in Types)
    {
        DoSmth(type);
    }
}

private void DoSmth(Type t)
{
    switch (this.value) {
        case X xval:
            //Handle type X
            break;
        case Y xval:
            //Handle type Y
            break;
        //And so on...
    }
}
Chrille
  • 1,435
  • 12
  • 26