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

  4.3 获取泛型类型

  问题

  您需要在运行时获得个泛型类型例子Type对象

  解决方案

  在使用typeof操作符时提供类型参数;使用类型参数例子化泛型类型用GetType思路方法

  声明般类型和个泛型类型如下:

public Simple
{
  public Simple
  {
  }
}
  
public SimpleGeneric<T>
{
  public SimpleGeneric
  {
  }
}


  使用typeof操作符和简单类型名称就可以在运行时获得简单类型类型对于泛型类型来说typeof时类型参数必须要提供但是简单类型例子和泛型类型例子都可以使用相同方式来GetType

Simple s = Simple;
  Type t = typeof(Simple);
  Type alsoT = s.GetType;
  //提供类型参数就才可以获得类型例子
  Type gtInt = typeof(SimpleGeneric<>);
  Type gtBool = typeof(SimpleGeneric<bool>);
  Type gtString = typeof(SimpleGeneric<>);
  // 当有个泛型类例子时您也可以使用GetType方式去个例子.
  SimpleGeneric<> sgI = SimpleGeneric<>;
Type alsoGT = sgI.GetType;


  讨论

  不能直接获取泛型类类型如果不提供个类型参数泛型类将没有类型(参考秘诀4.2获得更多信息)只有通过类型参数例子化泛型类才有Type

  如果您在使用typeof操作符时只提供泛型类型定义而不提供类型参数将得到下面:

// 这产生:
  // Error 26 Using the generic type 'CSharpRecipes.Generics.SimpleGeneric<T>'
  // requires '1' type arguments
  Type gt = typeof(SimpleGeneric);


  阅读参考

  查看秘诀4.2;参考MSDN文档中“typeof”主题

  4.4 使用相应泛型版本替换ArrayList

  问题

  您希望通过将所有ArrayList对象替换为相应泛型版本以提高应用效率并使得代码更易于使用当结构体或其他值类型存储在这些数据结构中时会导致装箱/拆箱操作这时就需要这么做

  解决方案

  使用更有效率泛型类.Collections.Generic.List来替换已存在.Collection.ArrayList类

  下面是使用.Collection.ArrayList对象简单例子:

public void UseNonGenericArrayList
  {
    // 创建个ArrayList.
    ArrayList numbers = ArrayList;
    numbers.Add(1); // 导致装箱操作
    numbers.Add(2); // 导致装箱操作
    // 显示ArrayList内所有整数
    // 每次迭代都导致拆箱操作
    foreach ( i in numbers)
    {
      Console.WriteLine(i);
    }
    numbers.Clear;
}


  相同代码使用了.Collections.Generic.List对象

public void UseGenericList
  {
    // 创建个List.
    List<> numbers = List<>;
    numbers.Add(1);
    numbers.Add(2);
    // 显示List中所有整数.
    foreach ( i in numbers)
    {
      Console.WriteLine(i);
    }
    numbers.Clear;
}


  讨论

  所有应用几乎都会使用ArrayList从提升您应用执行效率开始是个不错选择对于应用中简单使用ArrayList地方来说这种替代是非常容易但有些地方需要注意例如泛型List类未实现Icloneable接口而ArrayList实现了它

  表4-1显示了两个类中等价成员

ArrayList类成员 等价泛型List类成员
Capacity 属性 Capacity属性
Count属性 Count属性
IsFixedSize属性 ((IList)myList).IsFixedSize
IsReadOnly属性 ((IList)myList).IsReadOnly
IsSynchronized属性 ((IList)myList).IsSynchronized
Item属性 Item属性
SyncRoot属性 ((IList)myList).SyncRoot
Adapter 静态思路方法 N/A
Add 思路方法 Add思路方法
AddRange思路方法 AddRange思路方法
N/A AsReadOnly思路方法
BinarySearch思路方法 BinarySearch思路方法
Clear思路方法 Clear思路方法
Clone思路方法 Getrange(0, numbers.Count)
Contains思路方法 Contains思路方法
N/A ConvertAll思路方法
CopyTo思路方法 CopyTo思路方法
N/A Exists思路方法
N/A Find思路方法
N/A FindAll思路方法
N/A FindIndex思路方法
N/A FindLast思路方法
N/A FindLastIndex思路方法
N/A ForEach思路方法
FixedSize 静态思路方法 N/A
Getrange思路方法 Getrange思路方法
IndexOf思路方法 IndexOf思路方法
Insert思路方法 Insert思路方法
InsertRange思路方法 InsertRange思路方法
LastIndexOf思路方法 LastIndexOf思路方法
ReadOnly 静态思路方法 AsReadOnly思路方法
Remove思路方法 Remove思路方法
N/A RemoveAll思路方法
RemoveAt思路方法 RemoveAt思路方法
RemoveRange思路方法 RemoveRange思路方法
Repeat 静态思路方法 使用for循环和Add思路方法
Reverse思路方法 Reverse思路方法
SetRange思路方法 InsertRange思路方法
Sort思路方法 Sort思路方法
Synchronized 静态思路方法 lock(myList.SyncRoot) {…}
ToArray思路方法 ToArray思路方法
N/A trimExcess思路方法
TRimToSize思路方法 trimToSize思路方法
N/A trueForAll思路方法

  表4-1中几个ArrayList成员和泛型List成员并非对应从属性开始说只有CapacityCount和Item属性两个类中都存在为了弥补List类中几个缺失属性可以把它显式转换为Ilist接口下面代码演示了如何使用这些显式转换以获得缺失属性

List<> numbers = List<>;
  Console.WriteLine(((IList)numbers).IsReadOnly);
  Console.WriteLine(((IList)numbers).IsFixedSize);
  Console.WriteLine(((IList)numbers).IsSynchronized);
  Console.WriteLine(((IList)numbers).SyncRoot);


  注意由于缺少返回同步版本泛型List代码和缺少返回固定尺寸泛型List代码,IsFixedSize和IsSynchronized属性将总是返回falseSyncRoot属性被时将总是返回相同对象本质上这个属性返回this指针微软已经决定从所有泛型集合类中去除创建同步成员功能做为代替他们推荐使用lock关键字去锁住整个集合或其他类型同步对象来满足您需要

  静态ArrayList.Repeat在泛型List中没有对应思路方法做为代替您可以使用下面泛型思路方法:

public void Repeat<T>(List<T> list, T obj, count)
  {
     (count < 0)
    {
      throw ( ArgumentException(
          "参数count 必须大于或等于零"));
    }
    for ( index = 0; index < count; index)
    {
      list.Add(obj);
    }
}


  这个泛型思路方法有 3个参数:

  list

  泛型List对象

  obj

  将被以指定次数添加进泛型List中对象

  count

  把obj添加进泛型类中次数

  Clone思路方法也没有出现在泛型List类中(这个类并没有实现Icloneable接口)您可以使用泛型List类GetRange思路方法做为替代

  List<> oldList = List<>;

  // 给oldList添加元素…

  List<> List = oldList.GetRange(0, oldList.Count);

  GetRange思路方法对List对象中个范围元素执行浅拷贝(跟ArrayList中Clone思路方法接近)在此例中这个范围是所有元素

  提示:ArrayList默认容量是16个元素而List<T>默认容量为4个元素这意味着当添加第17个元素时List<T>不得不改变尺寸(重新分配内存)3次而ArrayList只重新分配点在评估应用性能时需要被考虑

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

延伸阅读

最新评论

发表评论