练习

(1)下面哪些元素可以是泛型?

  1. a.
  2. b. 方法
  3. c. 属性
  4. d. 运算符重载
  5. e. 结构
  6. f. 枚举
答案:a、b和e是;c和d否,但它们可以使用由包含它们的类提供的泛型类型参数。f否。

(2)扩展Ch12Ex01中的Vector类,使*运算符返回两个矢量的点积。

答案:

  1. public static double operator (Vector op1, Vector op2)
    {
    try
    {
    double angleDiff = (double)(op2.ThetaRadians.Value -
    op1.ThetaRadians.Value);
    return op1.R.Value
    op2.R.Value * Math.Cos(angleDiff);
    }
    catch
    {
    return null;
    }
    }


  两个矢量的点积定义为两个矢量的大小与两个矢量之间夹角余弦的乘积。

(3)下面的代码存在什么错误?请加以修改。

  1. public class Instantiator<T>
  2. {
  3. public T instance;
  4. public Instantiator()
  5. {
  6. instance = new T();
  7. }
  8. }
答案:不在T上强制new()约束,就不能实例化T。在T上强制new()约束可以确保有一个公共的默认构造函数是可用的。

  1. public class Instantiator<T>
    where T : new()
    {
    public T instance;

    public Instantiator()
    {
    instance = new T();
    }
    }


(4)下面的代码存在什么错误?请加以修改。

  1. public class StringGetter<T>
  2. {
  3. public string GetString<T>(T item)
  4. {
  5. return item.ToString();
  6. }
  7. }
答案:同一个泛型类型参数T既用于泛型类,又用于泛型方法。需要重命名其中的一个或两个。例如:

  1. public class StringGetter<U>
    {
    public string GetString<T>(T item)
    {
    return item.ToString();
    }
    }


(5)创建一个泛型类ShortList<T>,它实现了IList<T>,包含一个项集合及集合的最大容量。这个最大容量应是一个整数,并可以提供给ShortList<T>的构造函数,或者默认为10。构造函数还应通过IEnumerable<T>参数获取项的最初列表。该类与List<T>的功能相同,但如果试图给集合添加太多的项,或者传递给构造函数的IEnumerable<T>包含太多的项,就会抛出IndexOutOfRangeException类型的异常。

答案:
  1. pbulic class ShortList<T> : IList<T>
  2. {
  3. protected IList<T> innerCollection;
  4. protected int maxSize = 10;
  5. public ShortList() : this(10)
  6. {
  7. }
  8. public ShortList(IEnumerable<T> list) : this(10, list)
  9. {
  10. }
  11. public ShortList(int size, IEnumerable<T> list)
  12. {
  13. maxSize = size;
  14. innerCollection = new List<T>(list);
  15. if(Count > maxSize)
  16. {
  17. ThrowTooManyItemsException();
  18. }
  19. }
  20. protected void ThrowTooManyItemsException()
  21. {
  22. throw new IndexOutOfRangeException(
  23. "Unable to add any more items, maximum size is " + maxSize.ToString()
  24. + " items.");
  25. }
  26. #region IList<T> Members
  27. public int IndexOf(T item)
  28. {
  29. return innerCollection.IndexOf(item);
  30. }
  31. public void Insert(int index, T item)
  32. {
  33. if(Count < maxSize)
  34. {
  35. innerCollection.Insert(index, item);
  36. }
  37. else
  38. {
  39. ThrowTooManyItemsException();
  40. }
  41. }
  42. public void RemoveAt(int index)
  43. {
  44. innerCollection.RemoveAt(index);
  45. }
  46. public T this[int index]
  47. {
  48. get
  49. {
  50. return innerCollection[index];
  51. }
  52. set
  53. {
  54. innerCollection[index] = value;
  55. }
  56. }
  57. #endregion
  58. #region ICollection<T> Members
  59. public void Add(T item)
  60. {
  61. if(Count < maxSize)
  62. {
  63. innerCollection.Add(item);
  64. }
  65. else
  66. {
  67. ThrowTooManyItemsException();
  68. }
  69. }
  70. public void Clear()
  71. {
  72. innerCollection.Clear();
  73. }
  74. public bool ConTains(T item)
  75. {
  76. return innerCollection.Contains(item);
  77. }
  78. public void CopyTo(T[] array, int arrayIndex)
  79. {
  80. innerCollection.CopyTo(array, arrayIndex);
  81. }
  82. public int Count
  83. {
  84. get
  85. {
  86. return innerCollection.Count;
  87. }
  88. }
  89. public bool IsReadOnly
  90. {
  91. get
  92. {
  93. return innerCollection.IsReadOnly;
  94. }
  95. }
  96. public bool Remove(T item)
  97. {
  98. return innerCollection.Remove(item);
  99. }
  100. #endregion
  101. #region IEnumerable<T> Members
  102. public IEnumerator<T> GetEnumerator()
  103. {
  104. return innerCollection.GetEnumerator();
  105. }
  106. #endregion
  107. #region IEnumerable Members
  108. IEnumerator IEnumerable.GetEnumerator()
  109. {
  110. return GetEnumerator();
  111. }
  112. #endregion
  113. }

(6)下面的代码可以进行编译吗?试说明原因。

  1. public interface IMethaneProducer<out T>
  2. {
  3. void BelchAt(T target);
  4. }
答案:不,类型参数T定义为协变。但协变参数类型只能用作方法的返回值,不能用作方法实参。否则就会得到如下编译错误(假定使用名称空间VarianceDemo):

  1. Invalid variance: The type parameter 'T' must be contravariantly valid on
    'VarianceDemo.IMethaneProcucer<T>.BelchAt(T)'. 'T' is covariant.