C#泛型学习01--理解泛型

一、什么时候使用泛型?

1.所使用的类型是否包含或操作未指定的数据类型(如集合类型)。如果您的类型只操作单一的指定类型,那么就没有必要去创建一个泛型类。

2.如果所使用的类型将操作值类型,那么就会产生装箱和拆箱操作,就应该考虑使用泛型来防止装箱和拆箱操作。

二、理解泛型

几个小实验就可以演示一般类型和泛型类型之间的区别。

 

View Code
public class StandardClass 
{
static int _count = 0; //StandardClass类的对象的表态计数器
int _maxItemCount; //项数目的最大值
object[] _items; //保存项的数组
int _currentItem = 0; //当前项数目
public StandardClass(int items) //构造函数
{
_count++; //对象数目加
_maxItemCount = items;
_items = new object[_maxItemCount]; //数组初始化
}
//用于添加项,为了适用于任何类型,使用了object类型
public int AddItem(object item)
{
if (_currentItem < _maxItemCount)
{
_items[_currentItem] = item;
return _currentItem++; //返回添加的项的索引
}
else
throw new Exception("Item queue is full");
}
//用于从类中取得指定项
public object GetItem(int index)
{
Debug.Assert(index < _maxItemCount); //设置断言
if (index >= _maxItemCount)
throw new ArgumentOutOfRangeException("index");
return _items[index]; //返回指定项
}
public int ItemCount //属性,指示当前项数目
{
get { return _currentItem; }
}
public override string ToString( )
{ //重载ToString方法,用于介绍类的情况
return "There are " + _count.ToString( ) +
" instances of " + this.GetType( ).ToString( ) +
" which contains " + _currentItem + " items of type " +
_items.GetType( ).ToString( ) + "";
}
}

 StandardClass类有一个整型静态成员变量_count,用于在实例构造器中计数。重载的ToString()方法打印在这个应用程序域中StandardClass类实例的数目。StandardClass类还包括一个object数组(_item),它的长度由构造方法中的传递的参数来决定。它实现了添加和获得项的方法(AddItem,GetItem),还有一个只读属性来获取数组中的项的数目(ItemCount)。

 

View Code
    public class GenericClass<T>
{
public static int _count = 0; //StandardClass类的对象的计数器
public int _maxItemCount; //项数目的最大值
public T[] _items; //保存项的数组
public int _currentItem = 0; //当前项数目
public int ItemCount
{
get { return _currentItem; }
}

#region--构造函数--
/// <summary>
/// 带int参数的构造函数
/// </summary>
/// <param name="items"></param>
public GenericClass(T s ,int items)
{
_count++; //对象数目加
_maxItemCount = items;
_items = new T[_maxItemCount]; //数组初始化
}
#endregion

#region--添加项--
/// <summary>
/// 用于添加项,为了适用于任何类型,使用了object类型
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public int AddItem(T item)
{
if (_currentItem < _maxItemCount)
{
_items[_currentItem] = item;
return _currentItem++;
}
else
{
throw new Exception("Item queue is full");
}
}
#endregion

#region--用于从类中取得指定项--
/// <summary>
/// 用于从类中取得指定项
/// </summary>
/// <param name="index"></param>
/// <returns>返回指定项</returns>
public T GetItem(int index)
{
if (index >= _maxItemCount)
{
throw new ArgumentOutOfRangeException("index");
}
return _items[index];
}
#endregion

#region--重写ToString--
/// <summary>
/// 重载ToString方法,用于介绍类的情况
/// </summary>
/// <returns>返回类的情况</returns>
public override string ToString()
{
return "There are " + _count.ToString() + " instances of " + this.GetType().ToString() + " which contains " + _currentItem + " items of type " + _items.GetType().ToString() + "";
}
#endregion
}

GenericClass<T>类是一个泛型类型,同样有静态成员变量_count,实例构造器中对实例数目进行计算,重载的ToString()方法告诉您有多少GenericClass<T>类的实例存在。GenericClass<T>也有一个_itmes数组和StandardClass类中的相应方法。

 

不同点:

1.看看_items数组的声明。泛型它声明为:T[] _items;而不是object[] _items;

2.AddItem方法使用一个类型T做为参数,而在StandardClass中使用object类型做为参数

3.GetItem现在的返回值类型T,StandardClass返回值为object类型

这个改变允许GenericClass<T>中的方法在数组中存储和获得具体的类型而非StandardClass中的允许存储所有的object类型。

View Code
public static void Main(string[] args)
{
//一般类
StandardClass A = new StandardClass();
Console.WriteLine(A);
StandardClass B = new StandardClass();
Console.WriteLine(B);
StandardClass C = new StandardClass();
Console.WriteLine(C);
//泛型
GenericClass<bool> gA = new GenericClass<bool>(false, 6);
Console.WriteLine(gA);
GenericClass<int> gB = new GenericClass<int>(1, 6);
Console.WriteLine(gB);
GenericClass<string> gC = new GenericClass<string>("s", 6);
Console.WriteLine(gC);
GenericClass<string> gD = new GenericClass<string>("v", 6);
Console.WriteLine(gD);
}

上述代码输出结果如下:

There are 1 instances of CSharpRecipes.Generics+StandardClass which contains 0 items of type System.Object[]...

There are 2 instances of CSharpRecipes.Generics+StandardClass which contains 0 items of type System.Object[]...

There are 3 instances of CSharpRecipes.Generics+StandardClass which contains 0 items of type System.Object[]...

There are 1 instances of CSharpRecipes.Generics+GenericClass`1[System.Boolean] which contains 0 items of type System.Boolean[]...

There are 1 instances of CSharpRecipes.Generics+GenericClass`1[System.Int32] which contains 0 items of type System.Int32[]...

There are 1 instances of CSharpRecipes.Generics+GenericClass`1[System.String] which contains 0 items of type System.String[]...

There are 2 instances of CSharpRecipes.Generics+GenericClass`1[System.String] which contains 0 items of type System.String[]...

泛型中的类型参数允许您在不知道使用何种类型的情况下提供类型安全的代码。在很多场合下,您希望类型具有某些指定的特征,这可以通过使用类型约束来实现。方法在类本身不是泛型的情况下也可以拥有泛型类型的参数。

注意当StandardClass拥有三个实例,GenericClass有一个声明为<bool>类型的实例,一个声明为<int>类型的实例,两个声明为<string>类型的实例。这意味着所有非泛型类都创建同一.NET类型对象,而所有泛型类都为指定类型实例创建自己的.NET类型对象。

示例代码中的StandardClass类有三个实例,因为CLR中只维护一个StandardClass类型。而在泛型中,每种类型都被相应的类型模板所维护,当创建一个类型实例时,类型实参被传入。说得更清楚一些就是为GenericClass<bool>产生一个类型,为GenericClass<int>产生一个类型,为GenericClass<string>产生第三个类型。

内部静态成员_count可以帮助说明这一点,一个类的静态成员实际上是跟CLR中的类型相连的。CLR对于给定的类型只会创建一次,并维护它一直到应用程序域卸载。这也是为什么在调用ToString方法时,输出显示有StandardClass的三个实例,而GenericClass<T>类型有1和2个实例。

转载于:https://www.cnblogs.com/chen3jian/archive/2012/03/01/2376462.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值