VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Objective-C编程 >
  • c#泛型秘诀2

制作者:剑锋冷月 单位:无忧统计网,www.51stat.net
  4.3 获取泛型的类型
  问题
  您需要在运行时获得一个泛型类型实例的Type对象。
  解决方案
  在使用typeof操作符时提供类型参数;使用类型参数实例化的泛型类型,用GetType()方法。
  声明一个一般类型和一个泛型类型如下:
public class Simple
{
  public Simple()
  {
  }
}
  
public class SimpleGeneric<T>
{
  public SimpleGeneric()
  {
  }
}
  使用typeof操作符和简单类型的名称就可以在运行时获得简单类型的类型。对于泛型类型来说,在调用typeof时类型参数必须要提供,但是简单类型实例和泛型类型实例都可以使用相同的方式来调用GetType()。
Simple s = new Simple();
  Type t = typeof(Simple);
  Type alsoT = s.GetType();
  //提供类型参数就才可以获得类型实例
  Type gtInt = typeof(SimpleGeneric<int>);
  Type gtBool = typeof(SimpleGeneric<bool>);
  Type gtString = typeof(SimpleGeneric<string>);
  // 当有一个泛型类实例时,您也可以使用GetType的旧的方式去调用一个实例。.
  SimpleGeneric<int> sgI = new SimpleGeneric<int>();
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对象替换为相应的泛型版本以提高应用程序的效率,并使得代码更易于使用。当结构体或其他值类型存储在这些数据结构中时,会导致装箱/拆箱操作,这时就需要这么做。
  解决方案
  使用更有效率的泛型类System.Collections.Generic.List来替换已存在的System.Collection.ArrayList类。
  下面是使用System.Collection.ArrayList对象的简单例子:
public static void UseNonGenericArrayList()
  {
    // 创建一个ArrayList.
    ArrayList numbers = new ArrayList();
    numbers.Add(1); // 导致装箱操作
    numbers.Add(2); // 导致装箱操作
    // 显示ArrayList内的所有整数
    // 每次迭代都导致拆箱操作
    foreach (int i in numbers)
    {
      Console.WriteLine(i);
    }
    numbers.Clear();
}
  相同的代码使用了System.Collections.Generic.List对象
public static void UseGenericList()
  {
    // 创建一个List.
    List<int> numbers = new List<int>();
    numbers.Add(1);
    numbers.Add(2);
    // 显示List中的所有整数.
    foreach (int 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的成员并非一一对应。从属性开始说,只有Capacity,Count和Item属性两个类中都存在。为了弥补List类中的几个缺失的属性,可以把它显式转换为Ilist接口。下面的代码演示了如何使用这些显式转换以获得缺失的属性。
List<int> numbers = new List<int>();
  Console.WriteLine(((IList)numbers).IsReadOnly);
  Console.WriteLine(((IList)numbers).IsFixedSize);
  Console.WriteLine(((IList)numbers).IsSynchronized);
  Console.WriteLine(((IList)numbers).SyncRoot);
  注意,由于缺少返回同步版本的泛型List代码和缺少返回固定尺寸的泛型List代码,IsFixedSize和IsSynchronized属性将总是返回false。SyncRoot属性被调用时将总是返回相同的对象,本质上这个属性返回this指针。微软已经决定从所有泛型集合类中去除创建同步成员的功能。做为代替,他们推荐使用lock关键字去锁住整个集合或其他类型的同步对象来满足您的需要。
  静态的ArrayList.Repeat在泛型List中没有对应的方法。做为代替,您可以使用下面的泛型方法:
public static void Repeat<T>(List<T> list, T obj, int count)
  {
    if (count < 0)
    {
      throw (new ArgumentException(
          "参数count 必须大于或等于零"));
    }
    for (int index = 0; index < count; index++)
    {
      list.Add(obj);
    }
}
  这个泛型方法有三个参数:
  list
  泛型List对象
  obj
  将被以指定次数添加进泛型List中的对象
  count
  把obj添加进泛型类中的次数
  因为Clone方法也没有出现在泛型List类中(因为这个类并没有实现Icloneable接口),您可以使用泛型List类的GetRange方法做为替代。
  List<int> oldList = new List<int>();
  // 给oldList添加元素…
  List<int> newList = oldList.GetRange(0, oldList.Count);
  GetRange方法对List对象中一个范围的元素执行浅拷贝(跟ArrayList中的Clone方法接近)。在此例中这个范围是所有元素。
  提示:ArrayList默认的初始容量是16个元素,而List<T>的默认初始容量为4个元素。这意味着当添加第17个元素时,List<T>不得不改变尺寸(重新分配内存)3次,而ArrayList只重新分配一次。这一点在评估应用程序性能时需要被考虑。

相关教程