ここでは,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