Reputation: 17
So, I am trying to make a custom stack in C#. My problem is the parameter type. I want the stack to be a stack of any parameter type (CustomStack<string>
, CustomStack<int>
, CustomStack<double>
etc).
When i declare my CustomStack class, it needs a parameter type (for example CustomStack<int> cs = new CustomStack<int>)
The problem is if my custom stack has a parameter type int, it cannot accept doubles, strings, chars etc.
This is my class:
public class CustomStack<T> : IEnumerable<T>
{
private readonly IList<T> stackData;
public CustomStack()
{
this.stackData = new List<T>();
}
public void Push(params T[] items)
{
...
}
public void Pop()
{
...
}
public void Print()
{
...
}
public IEnumerator<T> GetEnumerator()
{
for (int i = 0; i < 2; i++)
{
for (int j = this.stackData.Count - 1; j >= 0; j--)
{
yield return this.stackData[j];
}
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
And here is my Main method:
public static void Main()
{
CustomStack<int> customStack = new CustomStack<int>();
Console.WriteLine("Enter one of the following commands:");
Console.WriteLine("PUSH - Pushes an element/s into the stack.");
Console.WriteLine("POP - Pops an element from the stack.");
Console.WriteLine("END - Exit the program.");
Console.WriteLine("PRINT - Prints the stack into the console.");
Console.WriteLine();
string input = Console.ReadLine();
while (input != "END")
{
string[] parts = input.Split(' ', StringSplitOptions.RemoveEmptyEntries);
string command = parts[0];
try
{
switch (command)
{
case "PUSH":
//here is the problem.
var item = parts.Skip(1).ToArray();
int intTemp;
double doubleTemp;
if (parts.Length == 1)
{
Console.WriteLine("Command PUSH requires element/s to push. Example: PUSH 3; PUSH 5 6; PUSH abc def ghi;");
}
else if (int.TryParse(item[0], out intTemp))
{
customStack.Push(parts.Skip(1).Select(int.Parse).ToArray());
}
else if(double.TryParse(item[0], out doubleTemp))
{
customStack.Push(parts.Skip(1).Select(double.Parse).ToArray());
}
break;
case "POP":
customStack.Pop();
break;
case "PRINT":
customStack.Print();
break;
case "END":
break;
default:
Console.WriteLine("Command is not recognised");
break;
}
}
catch (Exception exp)
{
Console.WriteLine(exp.Message);
}
Console.WriteLine();
Console.WriteLine("Enter one of the following commands:");
Console.WriteLine("PUSH - Pushes an element into the stack.");
Console.WriteLine("POP - Pops an element from the stack.");
Console.WriteLine("END - Exit the program.");
Console.WriteLine("PRINT - Prints the stack into the console.");
Console.WriteLine();
input = Console.ReadLine();
}
}
How do i overcome this issue and have a custom stack, that accepts ANY type of parameter?
Upvotes: 0
Views: 799
Reputation: 48
It sounds like you want to instantiate your CustomStack object without defining the generic type but want the type to decide which generic type to use once you push an item into it.
This would mean the CustomStack does not know which generic type it should hold until an item is pushed. This, however, means that the generic type can not be resolved during compile time, which is a problem.
If you just want multiple CustomStack objects which hold different types then create one for each type:
var intStack = new CustomStack<int>();
var doubleStack = new CustomStack<double>();
var stringStack = new CustomStack<string>();
If you really want to resolve the valid type at runtime you will have to store the Type
of the first object that is pushed by calling object.GetType();
and test all future objects if they are of the same type. That way you wouldn't be able to use generics and would have to use the object
type to store your items.
If you just want to store double
and int
types then you could create a CustomStack object of type CustomStack<double>
as the double datatype is able to hold integer values. Be careful though because this can cause rounding errors when comparing your stored items with normal integers.
Upvotes: 1
Reputation: 17658
The generic typing is intended to help you to create type independence at build time.
It is not intended to create type independence at run-time.
A way to overcome this, is to use object
, as T
, but you'll soon discover you can also omit the generic typing in that case.
There are some ways to deal with this though; some examples:
Upvotes: 1