Richard Pawson
Richard Pawson

Reputation: 1526

Create a list of C# Funcs with different parameter types

I want to be able to create multiple Funcs each of which takes in an instance of a type and returns the same type e.g.:

Func<Foo, Foo>
Func<Bar, Bar>

And then add these to a List (or perhaps to a Dictionary, keyed by the type that the Func handles).

Then given any instance y (the type of which is not known at compile time), I want to retrieve and invoke the Func that will work for on y.

Is what I am asking for even possible?

Upvotes: 2

Views: 192

Answers (2)

Theraot
Theraot

Reputation: 40325

You can create a dictionary of delegates. Use the type as key.

Dictionary<Type, Delegate> _dictionary = new();

And we will need a method to add delegates:

bool Add<T>(Func<T, T> func)
{
    return _dictionary.TryAdd(typeof(T), func);
}

And one to call them:

static T DoIt<T>(T t)
{
    if (_dictionary.TryGetValue(typeof(T), out var func))
    {
        return ((Func<T, T>)func).Invoke(t);
    }
   
    throw new NotImplementedException();
}

Working example:

using System;
using System.Collections.Generic;
                    
public class Program
{
    private static Dictionary<Type, Delegate> _dictionary = new();
    
    public static void Main()
    {      
        Add<String>(InternalDoIt);
        Add<int>(InternalDoIt);
        DoIt("Hello World"); // Outputs "Hello World"
        DoIt(1); // Outputs "1"
        DoIt(DateTime.Now); // Throws NotImplementException
    }
    
    static bool Add<T>(Func<T, T> func)
    {
        return _dictionary.TryAdd(typeof(T), func);
    }
    
    static T DoIt<T>(T t)
    {
        if (_dictionary.TryGetValue(typeof(T), out var func))
        {
            return ((Func<T, T>)func).Invoke(t);
        }
        
        throw new NotImplementedException();
    }
    
    static string InternalDoIt(string str){
            Console.WriteLine(str);
            return str;
    }
    static int InternalDoIt(int i) {
            Console.WriteLine(i);
            return i;
    }
}

No puppies or kitties died in the making of this answer.

Upvotes: 8

Rand Random
Rand Random

Reputation: 7440

Have you considered the following approach?

using System;
                    
public class Program
{
    public static void Main()
    {
        DoIt("Hello World");
        DoIt(1);
        DoIt(DateTime.Now);
    }
    
    static dynamic DoIt(dynamic t)
    {
        return InternalDoIt(t);
    }
    
    static object InternalDoIt(object obj) => throw new NotImplementedException();
    static string InternalDoIt(string str){
            Console.WriteLine(str);
            return str;
    }
    static int InternalDoIt(int i) {
            Console.WriteLine(i);
            return i;
    }
}

https://dotnetfiddle.net/RoXK0M

Upvotes: 0

Related Questions