}

 public T Pop() {

  _pointer--;

  if (_pointer < 0) {

   throw new Exception('Stack is empty.');

  }

  return _elements[_pointer];

 }

}

As highlighted, you use the type T as a placeholder for the eventual data type that you want to use for the class. In other words, during the design stage of this class, you do not specify the actual data type that the MyStack class will deal with. The MyStack class is now known as a generic type.

When declaring the private member array _element, you use the generic parameter T instead of a specific type such as int or string:

private T[] _elements;

In short, you replace all specific data types with the generic parameter T.

You can use any variable name you want to represent the generic parameter. T is chosen as the generic parameter for illustration purposes.

If you want the MyStack class to manipulate items of type int, specify that during the instantiation stage (int is called the type argument):

MyStack<int> stack = new MyStack<int>(3);

The stack object is now known as a constructed type, and you can use the MyStack class normally:

stack.Push(1);

stack.Push(2);

stack.Push(3);

A constructed type is a generic type with at least one type argument.

In Figure 9-1 IntelliSense shows that the Push() method now accepts arguments of type int.

Figure 9-1 

Trying to push a string value into the stack like this:

stack.Push('A'); //---Error---

generates a compile-time error. That's because the compiler checks the data type used by the MyStack class during compile time. This is one of the key advantages of using generics in C#.

To use the MyStack class for String data types, you simply do this:

MyStack<string> stack = new MyStack<string>(3);

stack.Push('A');

stack.Push('B');

stack.Push('C');

Figure 9-2 summarizes the terms used in a generic type.

Figure 9-2

Using the default Keyword in Generics

In the preceding implementation of the generic MyStack class, the Pop() method throws an exception whenever you call it when the stack is empty:

public T Pop() {

 _pointer--;

 if (_pointer < 0) {

  throw new Exception('Stack is empty.');

 }

 return _elements[_pointer];

}

Rather than throwing an exception, you might want to return the default value of the type used in the class. If the stack is dealing with int values, it should return 0; if the stack is dealing with string, it should return an empty string. In this case, you can use the default keyword to return the default value of a type:

public T Pop() {

 _pointer--;

 if (_pointer < 0) {

  return default(T);

 }

 return _elements[_pointer];

}

For instance, if the stack deals with int values, calling the Pop() method on an empty stack will return 0:

MyStack<int> stack = new MyStack<int>(3);

stack.Push(1);

stack.Push(2);

stack.Push(3);

Console.WriteLine(stack.Pop()); //---3---

Console.WriteLine(stack.Pop()); //---2---

Console.WriteLine(stack.Pop()); //---1---

Console.WriteLine(stack.Pop()); //---0---

Likewise, if the stack deals with the string type, calling Pop() on an empty stack will return an empty string:

MyStack<string> stack = new MyStack<string>(3);

stack.Push('A');

stack.Push('B');

stack.Push('C');

Console.WriteLine(stack.Pop()); //---'C'---

Console.WriteLine(stack.Pop()); //---'B'---

Console.WriteLine(stack.Pop()); //---'A'---

Console.WriteLine(stack.Pop()); //---''---

The default keyword returns null for reference types (that is, if T is a reference type) and 0 for numeric types. If the type is a struct, it will return each member of the struct initialized to 0 (for numeric types) or null (for reference types).

Вы читаете C# 2008 Programmer's Reference
Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату