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); } } } ```