ここでは,Y.Terada 氏による『エクストリーム・トレーニング』―『- eXtreme Training - Stack クラスの作成』の C# + NUnit 移植版を,Y.Terada 氏の許可を得てご紹介します.
オリジナルは,上記サイトに有ります.
Copyright © 2004 Y.Terada
テスト成功
テスト失敗
コンパイルエラー
StackTest.cs (新規作成)
using System;
using NUnit.Framework;
[TestFixture]
public class StackTest
{
}
Stack.cs (新規作成)
using System;
class Stack
{
}
StackTest.cs
[TestFixture] public class StackTest { [Test] public void TestConstructor() { Assert.Fail("no implementation"); } }
StackTest.cs
[TestFixture] public class StackTest { [Test] public void TestConstructor() { Assert.Fail("no implementation"); Stack stack = new Stack(); Assert.IsTrue(stack.IsEmpty); } }
Stack.cs
class Stack { public bool IsEmpty { get { return true; // 仮実装 } } }
StackTest.cs
[TestFixture] public class StackTest { … [Test] public void TestPush() { Assert.Fail("no implementation"); } }
StackTest.cs
[Test] public void TestPush() { Assert.Fail("no implementation"); Stack stack = new Stack(); stack.Push(3); Assert.IsFalse(stack.IsEmpty); }
Stack.cs
class Stack { public bool IsEmpty { get { return true; // 仮実装 } } public void Push(int x) { } }
Stack.cs
class Stack { public bool IsEmpty { get { return true; // 仮実装 return isEmpty; } } public void Push(int x) { isEmpty = false; } private bool isEmpty = true; }
StackTest.cs
[Test]
public void TestPush()
{
Stack stack = new Stack();
stack.Push(3);
Assert.IsFalse(stack.IsEmpty);
Assert.AreEqual(3, stack.Top); // Top がない
}
Stack.cs
class Stack { … public int Top { get { return 3; // 仮実装 } } … }
StackTest.cs
[Test] public void TestPush() { Stack stack = new Stack(); stack.Push(3); Assert.IsFalse(stack.IsEmpty); Assert.AreEqual(3, stack.Top); // Top がない stack.Push(8); Assert.AreEqual(8, stack.Top); }
Stack.cs
class Stack { … public int Top { get { return 3; // 仮実装 return element; } } public void Push(int x) { isEmpty = false; element = x; } private bool isEmpty = true; private int element; }
StackTest.cs
[Test] public void TestPush() { Stack stack = new Stack(); stack.Push(3); Assert.IsFalse(stack.IsEmpty); Assert.AreEqual(3, stack.Top); stack.Push(8); Assert.AreEqual(8, stack.Top); stack.Top = 10; Assert.AreEqual(10, stack.Top); }
Stack.cs
class Stack { … public int Top { get { return element; } set { element = value; } } … }
StackTest.cs
[Test]
public void TestConstructor()
{
Stack stack = new Stack();
Assert.IsTrue(stack.IsEmpty);
Assert.AreEqual(0, stack.Size);
}
Stack.cs
class Stack { … public int Size { get { return 0; // 仮実装 } } … }
StackTest.cs
[Test]
public void TestPush()
{
Stack stack = new Stack();
stack.Push(3);
Assert.IsFalse(stack.IsEmpty);
Assert.AreEqual(1, stack.Size);
Assert.AreEqual(3, stack.Top );
stack.Push(8);
Assert.AreEqual(8, stack.Top);
…
}
Stack.cs
class Stack { … public int Size { get { return 0; // 仮実装 return isEmpty ? 0 : 1; // 仮実装 } } … }
StackTest.cs
[Test]
public void TestPush()
{
Stack stack = new Stack();
stack.Push(3);
Assert.IsFalse(stack.IsEmpty);
Assert.AreEqual(1, stack.Size);
Assert.AreEqual(3, stack.Top );
stack.Push(8);
Assert.AreEqual(2, stack.Size);
Assert.AreEqual(8, stack.Top );
…
}
Stack.cs
class Stack { … public int Size { get { return isEmpty ? 0 : 1; // 仮実装 return size; } } … public void Push(int x) { isEmpty = false; element = x; ++size; } private bool isEmpty = true; private int size = 0; private int element; }
Stack.cs
…リファクタリング…
class Stack { … public bool IsEmpty { get { return isEmpty; return (size == 0); } } … public void Push(int x) { isEmpty = false; element = x; ++size; } private bool isEmpty = true; private int size = 0; private int element; }
StackTest.cs
[TestFixture] public class StackTest { … [Test] public void TestPop() { Assert.Fail("no implementation"); } }
StackTest.cs
[Test] public void TestPop() { Assert.Fail("no implementation"); Stack stack = new Stack(); stack.Push(3); stack.Pop(); Assert.IsTrue(stack.IsEmpty); Assert.AreEqual(0, stack.Size); }
Stack.cs
class Stack { … public void Pop() { size = 0; // 仮実装 } … }
StackTest.cs
[Test] public void TestPop() { Stack stack = new Stack(); stack.Push(3); stack.Push(5); stack.Pop(); Assert.AreEqual(1, stack.Size); stack.Pop(); Assert.IsTrue(stack.IsEmpty); Assert.AreEqual(0, stack.Size); }
Stack.cs
class Stack { … public void Pop() { size = 0; // 仮実装 System.Diagnostics.Debug.Assert(size > 0); --size; } … }
StackTest.cs
[Test]
public void TestPop()
{
Stack stack = new Stack();
stack.Push(3);
stack.Push(5);
stack.Pop();
Assert.AreEqual(1, stack.Size);
Assert.AreEqual(3, stack.Top );
stack.Pop();
Assert.IsTrue(stack.IsEmpty);
Assert.AreEqual(0, stack.Size);
}
Stack.cs
class Stack { … public int Top { get { return element; System.Diagnostics.Debug.Assert(size > 0); return elements[size - 1]; } set { element = value; System.Diagnostics.Debug.Assert(size > 0); elements[size - 1] = value; } } public void Push(int x) { element = x; ++size; System.Diagnostics.Debug.Assert(size < 2); elements[size++] = x; } … private int size = 0; private int element; private int[] elements = new int[2]; }
Stack.cs
class Stack { … public void Push(int x) { System.Diagnostics.Debug.Assert(size < 2); int[] temporary = new int[size + 1]; if (elements != null) Array.Copy(elements, temporary, size); elements = temporary; elements[size++] = x; } … private int size = 0; private int[] elements = new int[2]; private int[] elements = null; }
Stack.cs
class Stack { … public void Push(int x) { int[] temporary = new int[size + 1]; if (elements != null) Array.Copy(elements, temporary, size); elements = temporary; if (capacity <= size) { capacity = (capacity == 0) ? 8 : capacity * 2; int[] temporary = new int[capacity]; if (elements != null) Array.Copy(elements, temporary, size); elements = temporary; } elements[size++] = x; } … private int size = 0; private int capacity = 0; private int[] elements = null; }
StackTest.cs
… [Test] public void TestClone() { Assert.Fail("no implementation"); } …
StackTest.cs
[Test] public void TestClone() { Assert.Fail("no implementation"); Stack source = new Stack(); source.Push(3); Stack destination = (Stack)source.Clone(); }
Stack.cs
class Stack : ICloneable { … public object Clone() { Stack stack = new Stack(); return stack; } … }
StackTest.cs
[Test] public void TestClone() { Stack source = new Stack(); source.Push(3); Stack destination = (Stack)source.Clone(); Assert.AreEqual(source.Top , destination.Top ); Assert.AreEqual(source.Size, destination.Size); destination.Pop(); destination.Push(5); Assert.IsFalse(source.Top == destination.Top); }
Stack.cs
class Stack : ICloneable { … public object Clone() { Stack stack = new Stack(); stack.size = size ; stack.capacity = capacity; if (elements != null) { stack.elements = (int[])elements.Clone(); } return stack; } … }
StackTest.cs
… [Test] public void TestCopy() { Assert.Fail("no implementation"); } …
StackTest.cs
[Test] public void TestCopy() { Assert.Fail("no implementation"); Stack source = new Stack(); source.Push(3); Stack destination = new Stack(); Stack.Copy(source, destination); }
Stack.cs
class Stack : ICloneable { … public static void Copy(Stack source, Stack destination) { } … }
StackTest.cs
[Test] public void TestCopy() { Stack source = new Stack(); source.Push(3); Stack destination = new Stack(); Stack.Copy(source, destination); Assert.AreEqual(source.Top , destination.Top ); Assert.AreEqual(source.Size, destination.Size); destination.Pop(); destination.Push(5); Assert.IsFalse(source.Top == destination.Top); }
Stack.cs
class Stack : ICloneable { … public static void Copy(Stack source, Stack destination) { destination.size = source.size ; destination.capacity = source.capacity; destination.elements = new int[source.capacity]; if (source.size > 0) { Array.Copy(source.elements, destination.elements, source.size); } } … }
StackTest.cs
[Test] public void TestEmptyTop() { Assert.Fail("no implementation"); }
StackTest.cs
[Test] public void TestEmptyTop() { Assert.Fail("no implementation"); Stack stack = new Stack(); try { int x = stack.Top; Assert.Fail("ここには来ない筈"); } catch (InvalidOperationException expected) { } }
Stack.cs
public int Top { get { System.Diagnostics.Debug.Assert(size > 0); if (IsEmpty) throw new InvalidOperationException(); return elements[size - 1]; } set { System.Diagnostics.Debug.Assert(size > 0); elements[size - 1] = value; } }
StackTest.cs
[Test] public void TestEmptyTop() { Stack stack = new Stack(); try { int x = stack.Top; Assert.Fail("ここには来ない筈"); } catch (InvalidOperationException expected) { } try { stack.Top = 1; Assert.Fail("ここには来ない筈"); } catch (InvalidOperationException expected) { } }
Stack.cs
public int Top { get { if (IsEmpty) throw new InvalidOperationException(); return elements[size - 1]; } set { System.Diagnostics.Debug.Assert(size > 0); if (IsEmpty) throw new InvalidOperationException(); elements[size - 1] = value; } }
Stack.cs
…リファクタリング…
class Stack : ICloneable { … public int Top { get { if (IsEmpty) throw new InvalidOperationException(); EmptyCheck(); return elements[size - 1]; } set { if (IsEmpty) throw new InvalidOperationException(); EmptyCheck(); elements[size - 1] = value; } } … private void EmptyCheck() { if (IsEmpty) throw new InvalidOperationException(); } … }
StackTest.cs
[Test] public void TestEmptyPop() { Assert.Fail("no implementation"); }
StackTest.cs
[Test] public void TestEmptyPop() { Assert.Fail("no implementation"); Stack stack = new Stack(); try { stack.Pop(); Assert.Fail("ここには来ない筈"); } catch (InvalidOperationException expected) { } }
Stack.cs
public void Pop() { System.Diagnostics.Debug.Assert(size > 0); EmptyCheck(); --size; }
StackTest.cs
[Test] public void TestSwap() { Assert.Fail("no implementation"); }
StackTest.cs
[Test] public void TestSwap() { Assert.Fail("no implementation"); Stack stack1 = new Stack(); stack1.Push(1); stack1.Push(3); stack1.Push(5); Assert.AreEqual(3, stack1.Size); Assert.AreEqual(5, stack1.Top ); Stack stack2 = new Stack(); stack2.Push(2); stack2.Push(4); Assert.AreEqual(2, stack2.Size); Assert.AreEqual(4, stack2.Top ); stack1.Swap(stack2); Assert.AreEqual(2, stack1.Size); Assert.AreEqual(4, stack1.Top ); Assert.AreEqual(3, stack2.Size); Assert.AreEqual(5, stack2.Top ); }
Stack.cs
class Stack : ICloneable { … public void Swap(Stack stack) { Swap(ref size , ref stack.size ); Swap(ref capacity, ref stack.capacity); int[] temporary = elements ; elements = stack.elements; stack.elements = temporary ; } … private static void Swap(ref int x, ref int y) { int temporary = x ; x = y ; y = temporary; } … }
Stack.cs
class Stack : ICloneable { … public object Clone() { Stack stack = new Stack(); stack.size = size; stack.capacity = capacity; stack.capacity = IsEmpty ? 8 : size * 2; if (elements != null) { stack.elements = (int[])elements.Clone(); } stack.elements = new int[stack.capacity]; if (size > 0) { Array.Copy(elements, stack.elements, size); } return stack; } public static void Copy(Stack source, Stack destination) { destination.size = source.size; destination.capacity = source.capacity; destination.capacity = source.IsEmpty ? 8 : source.size * 2; destination.elements = new int[source.capacity]; destination.elements = new int[destination.capacity]; if (source.size > 0) { Array.Copy(source.elements, destination.elements, source.size); } } … public void Push(int x) { if (capacity <= size) { capacity = (capacity == 0) ? 8 : capacity * 2; int[] temporary = new int[capacity]; if (elements != null) Array.Copy(elements, temporary, size); elements = temporary; Stack temporary = (Stack)Clone(); Swap(temporary); } elements[size++] = x; } … }
Stack.cs
class Stack : ICloneable { … public void Push(int x) { if (capacity <= size) { Stack temporary = (Stack)Clone(); Swap(temporary); Swap((Stack)Clone()); } elements[size++] = x; } … }
StackTest.cs
● Generics が使用可能なとき
[TestFixture] public class StackTest { [Test] public void TestConstructor() { Stack stack = new Stack(); Stack<int> stack = new Stack<int>(); … } [Test] public void TestClone() { Stack source = new Stack(); Stack<int> source = new Stack<int>(); source.Push(3); Stack destination = (Stack)source.Clone(); Stack<int> destination = (Stack<int>)source.Clone(); … } [Test] public void TestCopy() { Stack source = new Stack(); Stack<int> source = new Stack<int>(); source.Push(3); Stack destination = new Stack(); Stack<int> destination = new Stack<int>(); … } [Test] void TestSwap() { Stack stack1 = new Stack(); Stack<int> stack1 = new Stack<int>(); … Stack stack2 = new Stack(); Stack<int> stack2 = new Stack<int>(); … } [Test] public void TestPush() { Stack stack = new Stack(); Stack<int> stack = new Stack<int>(); … } [Test] public void TestPop() { Stack stack = new Stack(); Stack<int> stack = new Stack<int>(); … } [Test] public void TestEmptyTop() { Stack stack = new Stack(); Stack<int> stack = new Stack<int>(); … } [Test] public void TestEmptyPop() { Stack stack = new Stack(); Stack<int> stack = new Stack<int>(); … } }
● Generics が使用できないとき
[Test] public void TestEmptyTop() { Stack stack = new Stack(); try { int x = stack.Top; int x = (int)stack.Top; Assert.Fail("ここには来ない筈"); } … }
Stack.cs
● Generics が使用可能なときのみ
class Stack : ICloneable class Stack<T> : ICloneable { … }
StackTest.cs
[Test] public void TestForMyValue() { Assert.Fail("no implementation"); }
StackTest.cs
● Generics が使用可能なとき
class MyValue { public int number; } [Test] public void TestForMyValue() { Assert.Fail("no implementation"); Stack<MyValue> stack = new Stack<MyValue>(); MyValue v = new MyValue(); v.number = 1; stack.Push(v); Assert.AreEqual(1, stack.Size); Assert.AreEqual(1, stack.Top.number); stack.Pop(); Assert.IsTrue(stack.IsEmpty); }
● Generics が使用できないとき
class MyValue { public int number; } [Test] public void TestForMyValue() { Assert.Fail("no implementation"); Stack stack = new Stack(); MyValue v = new MyValue(); v.number = 1; stack.Push(v); Assert.AreEqual(1, stack.Size); Assert.AreEqual(1, ((MyValue)stack.Top).number); stack.Pop(); Assert.IsTrue(stack.IsEmpty); }
Stack.cs
● Generics が使用可能なとき
class Stack<T> : ICloneable { … public int Top public T Top { get { EmptyCheck(); return elements[size - 1]; } set { EmptyCheck(); elements[size - 1] = value; } } public object Clone() // shallow copy (簡易コピー) { Stack stack = new Stack(); stack.size = size; stack.capacity = IsEmpty ? 8 : size * 2; stack.elements = new int[stack.capacity]; stack.elements = new T[stack.capacity]; if (size > 0) { Array.Copy(elements, stack.elements, size); } return stack; } public static void Copy(Stack source, Stack destination) // shallow copy (簡易コピー) { destination.size = source.size; destination.capacity = source.IsEmpty ? 8 : source.size * 2; destination.elements = new int[destination.capacity]; destination.elements = new T[destination.capacity]; if (source.size > 0) { Array.Copy(source.elements, destination.elements, source.size); } } public void Swap(Stack stack) { Swap(ref size , ref stack.size ); Swap(ref capacity, ref stack.capacity); int[] temporary = elements ; T[] temporary = elements ; elements = stack.elements; stack.elements = temporary ; } public void Push(int x) public void Push(T x) { if (capacity <= size) { Swap((Stack)Clone()); } elements[size++] = x; } … private int size = 0; private int capacity = 0; private int[] elements = null; private T[] elements = null; }
● Generics が使用できないとき
class Stack : ICloneable { … public int Top public object Top { get { EmptyCheck(); return elements[size - 1]; } set { EmptyCheck(); elements[size - 1] = value; } } public object Clone() // shallow copy (簡易コピー) { Stack stack = new Stack(); stack.size = size; stack.capacity = IsEmpty ? 8 : size * 2; stack.elements = new int[stack.capacity]; stack.elements = new object[stack.capacity]; if (size > 0) { Array.Copy(elements, stack.elements, size); } return stack; } public static void Copy(Stack source, Stack destination) // shallow copy (簡易コピー) { destination.size = source.size; destination.capacity = source.IsEmpty ? 8 : source.size * 2; destination.elements = new int[destination.capacity]; destination.elements = new object[destination.capacity]; if (source.size > 0) { Array.Copy(source.elements, destination.elements, source.size); } } public void Swap(Stack stack) { Swap(ref size , ref stack.size ); Swap(ref capacity, ref stack.capacity); int[] temporary = elements ; object[] temporary = elements ; elements = stack.elements; stack.elements = temporary ; } public void Push(int x) public void Push(object x) { if (capacity <= size) { Swap((Stack)Clone()); } elements[size++] = x; } … private int size = 0; private int capacity = 0; private int[] elements = null; private object[] elements = null; }
● Generics が使用可能なとき
StackTest.cs
using System; using NUnit.Framework; [TestFixture] public class StackTest { [Test] public void TestConstructor() { Stack<int> stack = new Stack<int>(); Assert.IsTrue(stack.IsEmpty); Assert.AreEqual(0, stack.Size); } [Test] public void TestCopy() { Stack<int> source = new Stack<int>(); source.Push(3); Stack<int> destination = (Stack<int>)source.Clone(); Assert.AreEqual(source.Top , destination.Top ); Assert.AreEqual(source.Size, destination.Size); destination.Pop(); destination.Push(5); Assert.IsFalse(source.Top == destination.Top); } [Test] public void TestSwap() { Stack<int> stack1 = new Stack<int>(); stack1.Push(1); stack1.Push(3); stack1.Push(5); Assert.AreEqual(3, stack1.Size); Assert.AreEqual(5, stack1.Top ); Stack<int> stack2 = new Stack<int>(); stack2.Push(2); stack2.Push(4); Assert.AreEqual(2, stack2.Size); Assert.AreEqual(4, stack2.Top ); stack1.Swap(stack2); Assert.AreEqual(2, stack1.Size); Assert.AreEqual(4, stack1.Top ); Assert.AreEqual(3, stack2.Size); Assert.AreEqual(5, stack2.Top ); } [Test] public void TestPush() { Stack stack<int> = new Stack<int>(); stack.Push(3); Assert.IsFalse(stack.IsEmpty); Assert.AreEqual(1, stack.Size); Assert.AreEqual(3, stack.Top ); stack.Push(8); Assert.AreEqual(2, stack.Size); Assert.AreEqual(8, stack.Top ); stack.Top = 10; Assert.AreEqual(10, stack.Top); } [Test] public void TestPop() { Stack stack<int> = new Stack<int>(); stack.Push(3); stack.Push(5); stack.Pop(); Assert.AreEqual(1, stack.Size); Assert.AreEqual(3, stack.Top ); stack.Pop(); Assert.IsTrue(stack.IsEmpty); Assert.AreEqual(0, stack.Size); } [Test] public void TestEmptyTop() { Stack<int> stack = new Stack<int>(); try { int x = stack.Top; Assert.Fail("ここには来ない筈"); } catch (InvalidOperationException expected) { } try { stack.Top = 1; Assert.Fail("ここには来ない筈"); } catch (InvalidOperationException expected) { } } [Test] public void TestEmptyPop() { Stack<int> stack = new Stack<int>(); try { stack.Pop(); Assert.Fail("ここには来ない筈"); } catch (InvalidOperationException expected) { } } class MyValue { public int number; } [Test] public void TestForMyValue() { Stack<MyValue> stack = new Stack<MyValue>(); MyValue v = new MyValue(); v.number = 1; stack.Push(v); Assert.AreEqual(1, stack.Size); Assert.AreEqual(1, stack.Top.number); stack.Pop(); Assert.IsTrue(stack.IsEmpty); } }
Stack.cs
using System; class Stack<T> : ICloneable { public bool IsEmpty { get { return (size == 0); } } public int Size { get { return size; } } public T Top { get { EmptyCheck(); return elements[size - 1]; } set { EmptyCheck(); elements[size - 1] = value; } } public object Clone() // shallow copy (簡易コピー) { Stack stack = new Stack(); stack.size = size; stack.capacity = IsEmpty ? 8 : size * 2; stack.elements = new T[stack.capacity]; if (size > 0) { Array.Copy(elements, stack.elements, size); } return stack; } public static void Copy(Stack source, Stack destination) // shallow copy (簡易コピー) { destination.size = source.size; destination.capacity = source.IsEmpty ? 8 : source.size * 2; destination.elements = new T[destination.capacity]; if (source.size > 0) { Array.Copy(source.elements, destination.elements, source.size); } } public void Swap(Stack stack) { Swap(ref size , ref stack.size ); Swap(ref capacity, ref stack.capacity); T[] temporary = elements ; elements = stack.elements; stack.elements = temporary ; } public void Push(T x) { if (capacity <= size) { Swap((Stack)Clone()); } elements[size++] = x; } public void Pop() { EmptyCheck(); --size; } private void EmptyCheck() { if (IsEmpty) throw new InvalidOperationException(); } private static void Swap(ref int x, ref int y) { int temporary = x ; x = y ; y = temporary; } private int size = 0; private int capacity = 0; private T[] elements = null; }
● Generics が使用可でないとき
StackTest.cs
using System; using NUnit.Framework; [TestFixture] public class StackTest { [Test] public void TestConstructor() { Stack stack = new Stack(); Assert.IsTrue(stack.IsEmpty); Assert.AreEqual(0, stack.Size); } [Test] public void TestClone() { Stack source = new Stack(); source.Push(3); Stack destination = (Stack)source.Clone(); Assert.AreEqual(source.Top , destination.Top ); Assert.AreEqual(source.Size, destination.Size); destination.Pop(); destination.Push(5); Assert.IsFalse(source.Top == destination.Top); } [Test] public void TestCopy() { Stack source = new Stack(); source.Push(3); Stack destination = new Stack(); Stack.Copy(source, destination); Assert.AreEqual(source.Top , destination.Top ); Assert.AreEqual(source.Size, destination.Size); destination.Pop(); destination.Push(5); Assert.IsFalse(source.Top == destination.Top); } [Test] public void TestSwap() { Stack stack1 = new Stack(); stack1.Push(1); stack1.Push(3); stack1.Push(5); Assert.AreEqual(3, stack1.Size); Assert.AreEqual(5, stack1.Top ); Stack stack2 = new Stack(); stack2.Push(2); stack2.Push(4); Assert.AreEqual(2, stack2.Size); Assert.AreEqual(4, stack2.Top ); stack1.Swap(stack2); Assert.AreEqual(2, stack1.Size); Assert.AreEqual(4, stack1.Top ); Assert.AreEqual(3, stack2.Size); Assert.AreEqual(5, stack2.Top ); } [Test] public void TestPush() { Stack stack = new Stack(); stack.Push(3); Assert.IsFalse(stack.IsEmpty); Assert.AreEqual(1, stack.Size); Assert.AreEqual(3, stack.Top ); stack.Push(8); Assert.AreEqual(2, stack.Size); Assert.AreEqual(8, stack.Top ); stack.Top = 10; Assert.AreEqual(10, stack.Top); } [Test] public void TestPop() { Stack stack = new Stack(); stack.Push(3); stack.Push(5); stack.Pop(); Assert.AreEqual(1, stack.Size); Assert.AreEqual(3, stack.Top ); stack.Pop(); Assert.IsTrue(stack.IsEmpty); Assert.AreEqual(0, stack.Size); } [Test] public void TestEmptyTop() { Stack stack = new Stack(); try { int x = (int)stack.Top; Assert.Fail("ここには来ない筈"); } catch (InvalidOperationException expected) { } try { stack.Top = 1; Assert.Fail("ここには来ない筈"); } catch (InvalidOperationException expected) { } } [Test] public void TestEmptyPop() { Stack stack = new Stack(); try { stack.Pop(); Assert.Fail("ここには来ない筈"); } catch (InvalidOperationException expected) { } } class MyValue { public int number; } [Test] public void TestForMyValue() { Stack stack = new Stack(); MyValue v = new MyValue(); v.number = 1; stack.Push(v); Assert.AreEqual(1, stack.Size); Assert.AreEqual(1, ((MyValue)stack.Top).number); stack.Pop(); Assert.IsTrue(stack.IsEmpty); } }
Stack.cs
using System; class Stack : ICloneable { public bool IsEmpty { get { return (size == 0); } } public int Size { get { return size; } } public object Top { get { EmptyCheck(); return elements[size - 1]; } set { EmptyCheck(); elements[size - 1] = value; } } public object Clone() // shallow copy (簡易コピー) { Stack stack = new Stack(); stack.size = size; stack.capacity = IsEmpty ? 8 : size * 2; stack.elements = new object[stack.capacity]; if (size > 0) { Array.Copy(elements, stack.elements, size); } return stack; } public static void Copy(Stack source, Stack destination) // shallow copy (簡易コピー) { destination.size = source.size; destination.capacity = source.IsEmpty ? 8 : source.size * 2; destination.elements = new object[destination.capacity]; if (source.size > 0) { Array.Copy(source.elements, destination.elements, source.size); } } public void Swap(Stack stack) { Swap(ref size , ref stack.size ); Swap(ref capacity, ref stack.capacity); object[] temporary = elements ; elements = stack.elements; stack.elements = temporary ; } public void Push(object x) { if (capacity <= size) { Swap((Stack)Clone()); } elements[size++] = x; } public void Pop() { EmptyCheck(); --size; } private void EmptyCheck() { if (IsEmpty) throw new InvalidOperationException(); } private static void Swap(ref int x, ref int y) { int temporary = x ; x = y ; y = temporary; } private int size = 0; private int capacity = 0; private object[] elements = null; }
Copyright © 2004 Y.Terada
Copyright © 1997-2008 Sho's Software