Я понимаю, что в большинстве случаев было бы полезно иметь однородный, безопасный для типов стек, но мне любопытно, возможно ли это, поскольку меня попросили создать стек для упражнения, которое принимает все типы.
Итак, у меня в настоящее время есть универсальный класс Stack для связанного списка, и мне интересно, есть ли способ сделать класс Node универсальным, чтобы узел Next мог иметь другой тип.Я знаю, что могу заставить стек принимать все типы, просто сделав все параметры типа object
вместо универсального, но я был предупрежден о влиянии на производительность упаковки и распаковки типов значений / передачи всех его элементов вбазовый объектный класс.
Итак, я реализовал его как Generic, но не смог найти решение, которое бы разрешало разные типы для каждого узла.Если бы я хотел избежать подхода object
, есть ли возможное решение?Даже если для этого нужен совсем другой подход, он не обязательно должен соответствовать этому подходу.
Надеюсь, это имеет смысл!Во всяком случае, вот реализация, которую я в настоящее время имею.Пожалуйста, дайте мне знать, что вы думаете.
Node.cs
namespace DataStructures
{
class Node<T>
{
public T Value { get; private set; }
public Node<T> Next { get; set; }
public Node(T value)
{
Value = value;
}
}
}
Stack.cs
namespace DataStructures
{
class Stack<T>
{
private Node<T> root;
public int Size { get; private set; } = 0;
public Stack()
{
}
public Stack(params T[] values)
{
foreach (var value in values)
Push(value);
}
public void Push(T value)
{
if (value == null)
throw new ArgumentNullException("value", "You cannot push a null value onto the stack");
var newNode = new Node<T>(value);
if (root != null)
newNode.Next = root;
root = newNode;
Size++;
}
public dynamic Peek()
{
if (root == null)
return null;
return root.Value;
}
public T Pop()
{
if (root == null)
throw new InvalidOperationException("The stack is empty, nothing to pop");
Size--;
var popped = root.Value;
root = root.Next;
return popped;
}
public bool TryPop(out dynamic popped)
{
if (root == null)
{
popped = null;
return false;
}
else
{
popped = Pop();
return true;
}
}
public bool IsEmpty() => root == null ? true : false;
public void Clear()
{
root = null;
}
}
}