Casting in generic abstract class that implements interface

c#, generics

Solution

Your problem is that `ICoinStack` has generic methods, like `Push<T>(T item)`, which basically says that an implementation of `ICoinStack` can accept an `item` of any type.

However, in your implementation `CoinStack<T>`, you want to limit `<T>` of `ICoinStack.Push<T>` to `<T>` of `CoinStack<T>`. The compiler should have already given you a warning, saying the type parameter `T` has the same name as the type parameter `T` of the outer type.

You have to fix your design, either by making `ICoinStack` itself generic (as in `ICoinStack<T>`), or change it's method to accept/return `object` (or even better: `Coin`) instead of `T`.

Example:

// accept/return Coin instead of T to keep ICoinStack
// and it's methods non-generic
public interface ICoinStack
{
   Coin Pop();
   void Push(Coin item);
}

// explicit interface implementation and the where T:Coin 
// constrain help us here to implement ICoinStack
public abstract class CoinStack<T> : ICoinStack where T:Coin
{
   private Queue<T> _stack = new Queue<T>();

   Coin ICoinStack.Pop() { return _stack.Dequeue(); }
   void ICoinStack.Push(Coin item) { _stack.Enqueue((T)item); }

   public T Pop() { return _stack.Dequeue(); }
   public void Push(T item) { _stack.Enqueue(item); }
}

// we need a cast in Pop<T>, and also the where T:Coin constrain
public class CoinMachine
{
   private static Dictionary<Type, ICoinStack> map;

   static CoinMachine()
   {
       map = new Dictionary<Type, ICoinStack>()
       {
           { typeof(Coin50), new CoinStack50() },
           { typeof(Coin25), new CoinStack25() }
       };
   }

   public static T Pop<T>() where T:Coin
   {
       var type = typeof(T);
       return (T)map[type].Pop();
   }

   public static void Push<T>(T item) where T:Coin
   {
       var type = typeof(T);
       map[type].Push(item);
   }
}

Problem

Given a base class `Coin` ``` public class Coin { } ``` and two derived classes `Coin50Cent` and `Coin25Cent` ``` public class Coin50 : Coin { } public class Coin25 : Coin { } ``` The task is to create an object of a `CoinMachine` (used for coin exchange, e.g. puting 50 cent coin returns two 25 cent coins) that corresponds the following requierments: `CoinMachine` must have two collections of `Coin25Cent` and `Coin50cent` objects. The collections must be derived from an abstract generic class `CoinStack<T>` that has two methods `void Push(T item); T Pop();` `CoinMachine` must work as follows ` ``` CoinMachine.Push(new Coin25()); // puts 25cent in 25c stack CoinMachine.Push(new Coin50()); // puts 50cent in 50c stack CoinMachine.Pop(); // gets 50cent from 50c stack CoinMachine.Pop(); // gets 25cent from 25c stack ``` ` Here's my implementation Seems like I have a problem with casting in abstract CoinStack class. ``` namespace ConsoleApplication1 { /* Given condition */ class Program { static void Main(string[] args) { CoinMachine.Push(new Coin25()); CoinMachine.Push(new Coin50()); CoinMachine.Pop<Coin50>(); CoinMachine.Pop<Coin25>(); } } public class Coin { } public class Coin50 : Coin { } public class Coin25 : Coin { } /* End given condition */ public interface ICoinStack { T Pop<T>(); void Push<T>(T item); } /* The problem within this abstract class */ public abstract class CoinStack<T> : ICoinStack { private Queue<T> _stack = new Queue<T>(); public T Pop<T>() { return _stack.Dequeue(); } public void Push<T>(T item) { _stack.Enqueue(item); } } public class CoinStack50 : CoinStack<Coin50> { } public class CoinStack25 : CoinStack<Coin25> { } public class CoinMachine { private static Dictionary<Type, ICoinStack> map; static CoinMachine() { map = new Dictionary<Type, ICoinStack>() { { typeof(Coin50), new CoinStack50() }, { typeof(Coin25), new CoinStack25() } }; } public static T Pop<T>() { var type = typeof(T); return map[type].Pop<T>(); } public static void Push<T>(T item) { var type = typeof(T); map[type].Push(item); } } } ```

Original source