1.如何声明和使用泛型
泛型是C#2.0和CLR(公共语言运行时)升级的一个新特性,泛型 为.NET 框架引入了一个叫 type parameters(类型参数)的概念,type parameters 使得程序在设计的时候,不必设计其具体的参数,其具体的参数可以延迟到需要的时候声明或调用。使用泛型代码运行时避免了类型转换的装箱和拆箱操作。
public class CommonMethod
{
/// <summary>
/// 打印个int值
/// </summary>
/// <param name="iParameter"></param>
public static void ShowInt(int iParameter)
{
Console.WriteLine("This is {0},parameter={1},type={2}",
typeof(CommonMethod).Name, iParameter.GetType().Name, iParameter);
}
/// <summary>
/// 打印个string值
/// </summary>
/// <param name="sParameter"></param>
public static void ShowString(string sParameter)
{
Console.WriteLine("This is {0},parameter={1},type={2}",
typeof(CommonMethod).Name, sParameter.GetType().Name, sParameter);
}
/// <summary>
/// 打印个DateTime值
/// </summary>
/// <param name="oParameter"></param>
public static void ShowDateTime(DateTime dtParameter)
{
Console.WriteLine("This is {0},parameter={1},type={2}",
typeof(CommonMethod).Name, dtParameter.GetType().Name, dtParameter);
}
/// <summary>
/// 打印个object值
/// 1 object类型是一切类型的父类
/// 2 任何父类出现的地方,都可以用子类来代替
/// </summary>
/// <param name="oParameter"></param>
public static void ShowObject(object oParameter)
{
Console.WriteLine("This is {0},parameter={1},type={2}",
typeof(CommonMethod), oParameter.GetType().Name, oParameter);
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tParameter"></param>
public static void Show<T>(T tParameter)
{
Console.WriteLine("This is {0},parameter={1},type={2}",
typeof(GenericMethod), tParameter.GetType().Name, tParameter.ToString());
}
}
class Program
{
static void Main(string[] args)
{
try
{
int iValue = 123;
string sValue = "456";
DateTime dtValue = DateTime.Now;
object oValue = "789";
Console.WriteLine("**************************");
CommonMethod.ShowInt(iValue);
//CommonMethod.ShowInt(sValue);//类型必须吻合
CommonMethod.ShowString(sValue);
CommonMethod.ShowDateTime(dtValue);
Console.WriteLine("**************************");
CommonMethod.ShowObject(oValue);
CommonMethod.ShowObject(iValue);
CommonMethod.ShowObject(sValue);
CommonMethod.ShowObject(dtValue);
Console.WriteLine("**************************");
CommonMethod.Show<object>(oValue);
CommonMethod.Show<int>(iValue);
CommonMethod.Show(iValue);//可以去掉,自动推算
//GenericMethod.Show<string>(iValue);//必须匹配
CommonMethod.Show<string>(sValue);
CommonMethod.Show<DateTime>(dtValue);
}
}
}
性能测试代码:
/// <summary>
/// 性能对比
/// </summary>
public class Monitor
{
public static void Show()
{
Console.WriteLine("****************Monitor******************");
{
int iValue = 12345;
long commonSecond = 0;
long objectSecond = 0;
long genericSecond = 0;
{
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 100000000; i++)
{
ShowInt(iValue);
}
watch.Stop();
commonSecond = watch.ElapsedMilliseconds;
}
{
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 100000000; i++)
{
ShowObject(iValue);
}
watch.Stop();
objectSecond = watch.ElapsedMilliseconds;
}
{
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 100000000; i++)
{
Show<int>(iValue);
}
watch.Stop();
genericSecond = watch.ElapsedMilliseconds;
}
Console.WriteLine("commonSecond={0},objectSecond={1},genericSecond={2}"
, commonSecond, objectSecond, genericSecond);
}
}
#region PrivateMethod
private static void ShowInt(int iParameter)
{
//do nothing
}
private static void ShowObject(object oParameter)
{
//do nothing
}
private static void Show<T>(T tParameter)
{
//do nothing
}
#endregion
}
3.泛型类, 泛型方法,泛型接口,泛型委托
/// <summary>
/// 泛型:就是为了满足不同类型,相同代码的重用
/// </summary>
/// <typeparam name="T"></typeparam>
public class GenericClass<T>
{
public T Property { get; set; }
/// <summary>
/// 泛型方法声明的时候,没有指定类型,而是调用的时候指定
/// 2.0泛型不是语法糖,而是由框架升级提供的功能
/// 泛型方法性能上和普通方法差不多的
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tParameter"></param>
public static void Show<T>(T tParameter)
{
Console.WriteLine("This is {0},parameter={1},type={2}",
typeof(GenericMethod), tParameter.GetType().Name, tParameter.ToString());
}
}
/// <summary>
/// 泛型接口
/// </summary>
/// <typeparam name="T"></typeparam>
public interface IGenericInterface<T>
{
}
/// <summary>
/// 泛型委托
/// </summary>
/// <typeparam name="T"></typeparam>
public delegate void DoNothing<T>();
/// <summary>
/// 普通类
/// </summary>
public class ChildClass : GenericClass<int>, IGenericInterface<string>//指定类型后的泛型,已经不是泛型的
{
}
public class ChildClassGeneric<T, S, V> : GenericClass<T>, IGenericInterface<S>
{
}
List<int> intList = new List<int>();
List<string> stringList = new List<string>();
//调用泛型类
GenericClass<int> iGenericClass = new GenericClass<int>();
iGenericClass.Property = 1;
GenericClass<string> sGenericClass = new GenericClass<string>();
sGenericClass.Property = "1233";
//普通类
ChildClass child = new ChildClass();
child.Property = 1;
ChildClassGeneric<int, string, DateTime> childClassGeneric = new ChildClassGeneric<int, string, DateTime>();
//委托
DoNothing<int> method = new DoNothing<int>(() => { });
3.泛型约束
public interface ISports
{
void Pingpang();
}
public interface IWork
{
void Work();
}
public class People
{
public int Id { get; set; }
public string Name { get; set; }
public void Hi()
{ }
}
public class Chinese : People, ISports, IWork
{
public void Tradition()
{
Console.WriteLine("仁义礼智信,温良恭俭让");
}
public void SayHi()
{
Console.WriteLine("吃了么?");
}
public void Pingpang()
{
Console.WriteLine("打乒乓球...");
}
public void Work()
{
throw new NotImplementedException();
}
}
public class Hubei : Chinese
{
public Hubei(int id)
{
}
public string Changjiang { get; set; }
public void Majiang()
{
Console.WriteLine("打麻将啦。。");
}
}
public class Japanese : ISports
{
public int Id { get; set; }
public string Name { get; set; }
public void Pingpang()
{
Console.WriteLine("打乒乓球...");
}
public void Hi()
{ }
}
public class Constraint
{
/// <summary>
/// 代码编译没问题,执行的时候才报错
/// 代码安全问题
/// </summary>
/// <param name="oParameter"></param>
public static void ShowObject(object oParameter)
{
Console.WriteLine("This is {0},parameter={1},type={2}",
typeof(CommonMethod), oParameter.GetType().Name, oParameter);
People people = (People)oParameter;
Console.WriteLine(people.Id);
Console.WriteLine(people.Name);
}
/// <summary>
/// 基类约束:
/// 1 带来权力,可以使用基类里面的属性和方法
/// 2 带来义务,类型参数必须是基类或者其子类
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tParameter"></param>
public static void Show<T>(T tParameter)
where T : People, ISports, new()//都是and 关系
{
Console.WriteLine("This is {0},parameter={1},type={2}",
typeof(GenericMethod), tParameter.GetType().Name, tParameter.ToString());
Console.WriteLine(tParameter.Id);
Console.WriteLine(tParameter.Name);
tParameter.Hi();
tParameter.Pingpang();
T t = new T();
}
public static void ShowPeople(People tParameter)
{
Console.WriteLine("This is {0},parameter={1},type={2}",
typeof(GenericMethod), tParameter.GetType().Name, tParameter.ToString());
Console.WriteLine(tParameter.Id);
Console.WriteLine(tParameter.Name);
tParameter.Hi();
//tParameter.Pingpang();
}
public static T DoNothing<T>(T tParameter)
//where T : ISports//接口约束
//where T : class//引用类型约束
//where T : struct//值类型约束
where T : new()//无参数构造函数约束
{
//tParameter.Pingpang();
//return null;
T t = new T();
return default(T);//会根据T的类型,去产生一个默认值
}
}
4.泛型的好处和原理
1)性能
对值类型使用非泛型集合类,在把值类型转换为引用类型,和把引用类型转换为值类型时,需要进行装箱和拆箱操作。装箱和拆箱的操作很容易实现,但是性能损失较大。假如使用泛型,就可以避免装箱和拆箱操作。
2)类型安全
与ArrayList类一样,如果使用对象,可以在这个集合中添加任意类型。
如果使用非泛型编程,如下代码,就有可能在某些情况下会发生异常。
3)二进制代码重用
泛型可以定义一次,用许多不同的类型实例化,不需要像C++模板那样访问源代码。泛型可以在一种语言中定义,在另一种.NET语言中使用。
4)代码的扩展
因为泛型类的定义会放在程序集中,所以用某个类型实例化泛型泛型类不会在IL代码中复制这些类。但是,在JIT编译器把泛型类编译为内部代码时,会给每个值类型创建一个新类。引用类型共享同一个内部类的所有实现代码。这是因为引用类型在实例化的泛型类中只需要4字节的内存单元(32位系统),就可以引用一个引用类型。值类型包含在实例化的泛型类的内存中。而每个值类型对内存的要求都不同,所以要为每个值类型实例化一个新类。