Generic Delegate C#
c#, delegates, generics
Solution
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.
old answer
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>`.
Problem
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 { } ```