Im trying to figure out how to make a generic delegate returning a generic value. My first non-generic scenario looks like this.
    delegate int FirstDelegate(int i);
    static FirstDelegate method;
    static void Main(string[] args)
    {
        method = ReturnInt;
        int i = method(3);
    }
    static int ReturnInt(int i)
    {
        return i;
    }
No problems here. Everything works fine. However when I make it generic things spin out of control.
    delegate T FirstDelegate<T>(T i);
    static FirstDelegate<T> method; <--
Already here he starts complaining about type or namespace etc etc not found. Anyone have any ideas of how to get this working?
Edit: My real goal is that I have a cache that can contain many different cache objects. And now I want a single method that is generic so I can get all objects through this one. I could make it return object or a baseclass, but then I still would have to cast each object everywhere its used.
Dog / cat example The non-generic parts are working.. the generic.. not so much
class Program
{
    static void Main(string[] args)
    {
        //Clientside
        Cache.method = GetAnimalOnClient;
        //not working
        Cache.methodGeneric = GetAnimalOnClientGeneric;
        var cat = Cache.GetCachedObj(AnimalType.Cat);
        var dog = Cache.GetCachedObj(AnimalType.Dog);
        //Want do
        vad dog = Cache.GetCachedObj<Dog>();
    }
    private static Animal GetAnimalOnClient(AnimalType type)
    {
        if (type == AnimalType.Dog)
            return Cache._Dogs.First();
        else
            return Cache._Cats.First();
    }
    /// <summary>
    /// This is the one I want to use
    /// </summary>
    private static T GetAnimalOnClientGeneric<T>() where T: Animal
    {
        if (typeof(T) == typeof(Cat))
            return Cache._Cats.First() as T;
        return Cache._Dogs.First() as T;
    }
}
public enum AnimalType
{
    Dog,
    Cat
}
public static class Cache
{
    delegate Animal GetCacheObjectDelegate(AnimalType type);
    public static GetCacheObjectDelegate method;
    delegate Animal GetCacheObjectDelegate<T>() where T : Animal;
    public static GetCacheObjectDelegate<T> methodGeneric; //<--Complains here
    public static List<Dog> _Dogs = new List<Dog>();
    public static List<Cat> _Cats = new List<Cat>();
    public static Animal GetCachedObj(AnimalType type)
    {
        return method(type);
    }
    public static T GetCachedObj<T>() where T: Animal
    {
        return methodGeneric<T>(); //NOPE
    }
}
public class Animal
{
}
public class Dog : Animal
{
}
public class Cat : Animal
{
}
                You're overcomplicating things.
public static class Cache
{
    private static List<Dog> _dogs = new List<Dog>();
    private static List<Cat> _cats = new List<Cat>();
    public static TAnimal GetCachedObj<TAnimal>() where T: Animal
    {
        if(TAnimal == typeof(Dog))
           return (TAnimal) _dogs.First();
        else if (TAnimal == typeof(Cat))
           return (TAnimal) _cats.First();
        else throw new InvalidOperationException("Invalid generic type argument");
    }
}
But your whole design has a flaw: it breaks the Liskov Substitution Principle.
The LSP states that if T (for example, Cat) is a subtype of Animal, then any instance of Animal can be replaced with T without any surprising effects.
Let me ellaborate. Say that you decide to create a new animal, a Giraffe. Now, if you call GetCachedObj<Giraffe>, you'll get an exception! The code does not work for any subtype of Animal, the LSP does not hold!
Instead you should make the cache class generic, and use a cache instance for every kind of animal
public class Cache<T> where T: Animal
{
    private static List<T> _animals = new List<T>();
    public T GetCachedObj()
    {
        return _animals.First();
    }
}
var dogsCache = new Cache<Dog>();
Dog dog = dogsCache.GetCachedObj();
var catsCache = new Cache<Cat>();
Cat cat = catsCache.GetCachedObj();
This will always work for any kind of animal.
Note: I believe Cache shouldn't be static. Instead, you can use the Singleton pattern to have one single cache instance across the application (per animal type), or use Dependency Injection (with a framework such as Castle Windsor) to inject a cache into every client.
You either bind the method's generic type argument to a specific type at declaration-time (as @Sean mentioned), or you make the enclosing type generic as well.
public class MyClass<T>
{
    public FirstDelegate<T> Method(){...}
}
You can also leave T unbound (without making the enclosing type generic), but you'll have to declare T after the method name, like so:
public FirstDelegate<T> Method<T>(){...}
Either way, at some point in time, T will be bound to a specific type. In this case, T will be bound when you create an instance of MyClass (i.e., new MyClass<int>), like you would do with a List<T>.
You need to specify the type when declaring method :
static FirstDelegate<int> method;
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With