java泛型:C#泛型秘诀(7)

  4.11 在泛型字典类中使用foreach

  问题

  您希望在实现了. Collections.Generic.IDictionary接口类型枚举元素.Collections.Generic.Dictionary 或 .Collections.Generic.SortedList

  解决方案

  最简单思路方法是在foreach循环中使用KeyValuePair结构体:

// 创建字典对象并填充.
  Dictionary<, > myStringDict = Dictionary<, >;
  myStringDict.Add(1, "Foo");
  myStringDict.Add(2, "Bar");
  myStringDict.Add(3, "Baz");
  // 枚举并显示所有键/值对.
  foreach (KeyValuePair<, > kvp in myStringDict)
  {
    Console.WriteLine("key  " + kvp.Key);
    Console.WriteLine("Value " + kvp.Value);
}


  讨论

  非泛型类.Collections.Hashtable (对应泛型版本为.Collections.Generic.Dictionary ), .Collections.CollectionBase和.Collections.SortedList 类支持在foreach使用DictionaryEntry类型:

foreach (DictionaryEntry de in myDict)
  {
    Console.WriteLine("key " + de.Key);
    Console.WriteLine("Value " + de.Value);
}


  但是Dictionary对象支持在foreach循环中使用KeyValuePair<T,U>类型这是GetEnumerator思路方法返回个Ienumerator而它依次返回KeyValuePair<T,U>类型而不是DictionaryEntry类型

  KeyValuePair<T,U>类型非常合适在foreach循环中枚举泛型Dictionary类DictionaryEntry类型包含是键和值object对象而KeyValuePair<T,U>类型包含是键和值在创建个Dictionary对象是被定义原本类型这提高了性能并减少了代码量您不再需要把键和值转化为它们原来类型

  阅读参考

  查看MSDN文档中.Collections.Generic.Dictionary Class”、“.Collections.Generic. SortedList Class”和“.Collections.Generic.KeyValuePair Structure”主题

  4.12类型参数约束

  问题

  您希望创建泛型类型时类型参数支持指定接口如IDisposable

  解决方案

  使用约束强制泛型类型参数实现个或多个指定接口:

public DisposableList<T> : IList<T>
    where T : IDisposable
  {
    private List<T> _items = List<T>;
    // 用于释放列表中项目私有思路方法
    private void Delete(T item)
    {
      item.Dispose;
    }
}


  DisposableList只接收实现了IDisposable接口对象做为它类型实参这样无论什么时候从DisposableList对象中移除个对象时那个对象Dispose思路方法总是被这使得您可以很容易处理存储在DisposableList对象中所有对象

  下面代码演示了DisposableList对象使用:

public void TestDisposableListCls
  {  
    DisposableList<StreamReader> dl = DisposableList<StreamReader>;
    // 创建些测试对象.
    StreamReader tr1 = StreamReader("c:oot.ini");
    StreamReader tr2 = StreamReader("c:autoexec.bat");
    StreamReader tr3 = StreamReader("c:config.sys");
    // 在DisposableList内添加些测试对象.
    dl.Add(tr1);
    dl.Insert(0, tr2);
    dl.Add(tr3);
    foreach(StreamReader sr in dl)
    {
      Console.WriteLine("sr.ReadLine " + sr.ReadLine);
    }
    // 在元素从DisposableList被移除的前将它们Dispose思路方法
    dl.RemoveAt(0);
    dl.Remove(tr1);
    dl.Clear;
}


  讨论

  where关键字用来约束个类型参数只能接收满足给定约束实参例如DisposableList约束所有类型实参T必须实现IDisposable接口:

public DisposableList<T> : IList<T>
    where T : IDisposable


  这意味着下面代码将成功编译:

  DisposableList<StreamReader> dl = DisposableList<StreamReader>;

  但下面代码不行:

  DisposableList<> dl = DisposableList<>;

  这是类型没有实现IDisposable接口而StreamReader类型实现了

  除了个或多个指定接口需要被实现外类型实参还允许其他约束您可以强制类型实参继承自个指定类如Textreader类:

public DisposableList<T> : IList<T>
    where T : .IO.TextReader, IDisposable


  您也可以决定是否类型实参仅为值类型或引用类型下面类声明被约束为只使用值类型:

public DisposableList<T> : IList<T>
     where T : struct


  这个类型声明为只能使用引用类型:

public DisposableList<T> : IList<T>
     where T :


  另外您也可能会需要些类型实参实现了公有默认构造思路方法:

public DisposableList<T> : IList<T>
     where T : IDisposable,


  使用约束允许您编写只接收部分类型实参泛型类型如果本节中解决方案忽略了IDisposable约束有可能会引发个编译这是并非所有DisaposableList类类型实参都实现了IDisposable接口如果您跳过这个编译期检查DisaposableList对象就可能会包含个没有公有无参Dispose思路方法对象些例中将会引发个运行期异常



  给泛型指定约束强制类类型实参进行严格类型检查并使得您在编译期发现问题而不是运行期



Tags:  泛型编程与stl 泛型编程 .net泛型 java泛型

延伸阅读

最新评论

发表评论