一、泛型
class Program
{
static void Main(string[] args)
{
Aint a = new Aint(2);
Console.WriteLine(a.Num);
Bstring b = new Bstring("a");
Console.WriteLine(b.Str);
Console.Read();
}
}
public class Aint
{
private int num;
public int Num { get { return num; } }
public Aint(int i)
{
num = i;
}
}
public class Bstring
{
private string str;
public string Str { get { return str; } }
public Bstring(string i)
{
str = i;
}
}
当两个模块的功能非常相似,却类型不同如果想要合并代码怎么办?
可以把类型改为object
public class Cobject
{
private object ob;
public object Ob { get { return ob; } }
public Cobject(object i)
{
ob = i;
}
}
虽然减少了代码量,但object不是类型安全的,而且会进行封箱拆箱。
所以泛型的作用:可以创建独立于被包含类型的类和方法。我们不必给不同的类型编写功能相同的许多方法或类,只创建一个方法或类即可。
static void Main(string[] args)
{
Example<string> a = new Example<string>("a");
System.Console.WriteLine(a.Ex);
Console.Read();
}
public class Example<T>
{
private T ex;
public T Ex { get { return ex; } }
public Example(T i)
{
ex = i;
}
}
通用类型T只是一个占位符,在实例化类时,根据用户指定的数据类型代替T并由即时编译器(JIT)生成本地代码,这个本地代码中已经使用了实际的数据类型,等同于用实际类型写的类,所以不同的封闭类的本地代码是不一样的。
所以可以认为:Example<string> a 和 Example<int> b是不同的类
他的优点显而易见:
1. 他是类型安全的。实例化了int类型的栈,就不能处理string类型的数据,其他数据类型也一样。
2. 无需装箱和折箱。这个类在实例化时,按照所传入的数据类型生成本地代码,本地代码数据类型已确定,所以无需装箱和拆箱。
二、默认值
public class Example<T>
{
public void Show(T str)
{
T a =default(T);
if (str != null)
a = str;
}
}
因为不知道是值类型,还是引用类型,所以不能给泛型赋值null或者0,要用default来设置,如果T是值类型则赋值null,反之0
三、泛型约束
现在有一个接口:
interface IName
{
string Name { get; set; }
}
如果想让泛型类来显示名字(Name):可以将T转换为IName来显示,但是如果T类型没有实现接口IName就会异常,所以需要给T规定:必须实现IName接口
class Ducument<T>
{
public void Show(T doc)
{
Console.WriteLine(((IName)doc).Name);
}
}
则:
class Ducument<T> where T:IName
如此可以这样写:
class Ducument<T> where T:IName
{
public void Show(IName doc)
{
Console.WriteLine(doc.Name);
}
}
最后: People类如果没有实现IName接口就会提示错误
class Program
{
static void Main(string[] args)
{
People a = new People("VenVertu");
Ducument<People> p = new Ducument<People>();
p.Show(a);
Console.Read();
}
}
interface IName
{
string Name { get; set; }
}
class People : IName
{
public string Name { get; set; }
public People(string name)
{
this.Name = name;
}
}
class Ducument<T> where T:IName
{
public void Show(IName doc)
{
Console.WriteLine("我叫 :"+doc.Name);
}
}
1.必须为值类型 T:class. 2.必须为引用类型 T:struct 3.必须有个无参构造函数 T:new()
继承一样可以有多个接口约束,只能有一个类约束,每个约束用逗号隔开。new()必须在最后一个。
四、泛型中的静态成员变量
class Program
{
static void Main(string[] args)
{
StaticDemo<int> a = new StaticDemo<int>();
StaticDemo<int> b = new StaticDemo<int>();
StaticDemo<string> str = new StaticDemo<string>();
Console.WriteLine(StaticDemo<int>.Count);
Console.WriteLine(StaticDemo<string>.Count);
Console.Read();
}
}
class StaticDemo<T>
{
public static int Count { get; set; }
public StaticDemo()
{
Count++;
}
}
结果是 输出2 和 1 :所以StaticDemo<int>和StaticDemo<string>是两个不同的类型
=========在所有弱点中,最大弱点就是暴露弱点===========