在实现 Stack 的过程中, 给定一个泛型参数 T, 假设 T 是引用类型, 则可以在栈为空的时候返回 null, 但如果是值类型就不行了, 那如何判断泛型参数是值类型还是引用类型呢? 这个就是这篇文章需要探索的内容.

IStack 接口定义如下所示:

cs
public interface IStack<T> {
    Boolean IsEmpty { get; }
    Int64 Count { get; }
    void Push(T value);

    T Pop();
    T Top { get; }
}

在实现过程中, 主要是 Pop 方法和 Top 属性二者的实现需要考虑值类型和引用类型的区别, 因为值类型没有 null.

在需要返回 T 类型对象的情况下, 有如下两种处理方式:

  1. 如果对值类型和引用类型合并考虑, 则可以返回 default(T). 这样的话, 如果 T 是引用类型, 则返回 null, 如果是值类型, 则返回对应的默认值(比如 int 默认是 0, char 默认是 \0 等等).

  2. 如果对值类型和引用类型分开考虑, 则可以在实现上对 T 添加泛型约束:

    cs
    // 对 T 添加泛型约束, 表明 T 是引用类型的.
    public class Stack<T> : IStack<T> where T : class { 
        //...
    }