c# 泛型,list<T>等


泛型是避免装箱拆箱造成的性能损失的有效方法,泛型是延迟声明的:即定义的时候没有指定具体的参数类型,把参数类型的声明推迟到了调用的时候
才指定参数类型。 延迟思想在程序架构设计的时候很受欢迎。例如:分布式缓存队列、EF的延迟加载等等。此外,泛型的效率一般比较高。
泛型类: 泛型里面成员都是强类型,<>内为类型,如int,string或自定义的class、接口等
namespace test02
{
//商店里卖各种物品,要有一个统一的包装,但是透过这个包装能看到不同商品的颜色或形状(不同属性)
class Program
{
static void Main(string[] args)
{
//生成一个里面全是苹果的泛型包装
Box<Apple> applebox = new Box<Apple>();
//将苹果放进去
Apple apple = new Apple() { Color = " red " };
applebox.Goodsname = apple;
//生成一个里面全是penbox的泛型包装
Pen pen = new Pen() { Xingzhuang = "rectangle" };
Box<Pen> penbox = new Box<Pen>() { Goodsname = pen };
Console.WriteLine(applebox.Goodsname.Color);
Console.WriteLine(penbox.Goodsname.Xingzhuang);
Console.ReadLine();
}
}
class Apple
{
public string Color
{
get; set;
}
}
class Pen
{
public string Xingzhuang { get; set; }
}
//泛型包装
class Box<Tgoods>
{
public Tgoods Goodsname { get; set; }
}
}
泛型接口:
如果一个类实现的是泛型接口,那这个类也是泛型的

刻画泛型时还有一个方法,直接在接口继承时刻画泛型接口,这样被继承的接口确定了,继承类就不再是泛型了

泛型方法:
我们在编写程序时,经常遇到两个模块的功能非常相似,只是一个是处理int数据,另一个是处理string数据,或者其他自定义的数据类型,但我们没有办法,只能分别写多个方法处理每个数据类型,因为方法的参数类型不同。有没有一种办法,在方法中传入通用的数据类型,这样不就可以合并代码了吗?泛型的出现就是专门解决这个问题的。
例子1:

例子2:
where关键字使形参继承接口,实现比较功能
class Program
{
static void Main(string[] args)
{
//不使用类型推断,指定int
Comp<int>(2, 3);
//使用类型推断,当做一般函数使用
Comp(2, 3);
}
/// <summary>
/// 泛型函数的使用,where关键字使形参继承接口,实现比较功能
/// </summary>
/// <typeparam name="t">泛型类型</typeparam>
/// <param name="a">参数</param>
/// <param name="b">参数</param>
public static void Comp<t>(t a,t b) where t:IComparable
{
int c= a.CompareTo(b);
Console.WriteLine(c);
}
}
//常规类,object类型
class Abc
{
} //自定义泛型类,T类型,没有指定继承,和上面的类功能一样
class Abc<T>
{
}
泛型委托: action<T>无返回值,func<T,T,Tresult>有返回值


泛型与lamd表达式结合:
lamd表达式定义:对于逻辑非常简单的函数,在调用的地方,谁调用谁声明,是匿名函数

where约束:
1.引用类型约束
class RefSample<T> where T:class 引用类型用Class表示约束。
表示对于的约束必须为一个类(引用类型)不能是值类型(int,char,datatime,struct),可以是接口interface
区分,数组为引用类型,因为定义数组时需要new出一个对象。
传入的必须为引用类型 但是RefSample仍然为值类型,两者无关性
2.值类型约束
class ValSample<T> where T:struct
int,char等类型都是struct,所有的值类型都有一个公共的无参构造函数
ValSample<int>
3.构造函数类型约束
where T:new(),所有的值类型都有一个公共的无参构造函数
指定的类型T必须有构造函数
4.转换类型约束
一种约束允许你指定另一个类型,类型实参必须可以通过一致性、引用或装箱转换隐式地转换为该类型。
理解的意思:可以互换,就是我们可以通过装箱或者强制类型转换成目标类型的 类型都可以用于类型参数传入。
class Sample<T> where T:Stream
有效:Sample<Stream> 这本身符合约束
无效:Sample<String> 因为String类型无法通过引用或者装箱拆箱强制转换成Stream、
struct Sample<T> where T:IDisposable
规定T必须为IDisposable 类型的 引用类型
有效:Sample<SqlConnection>引用转换
无效:Sample<StringBuilder>
分析:为什么SqlConnection 可以而StringBuilder不可以?它们都是引用类型
1.SqlConnection实现了IDisposable接口,所以可以协变


2.StringBuilder只实现了ISerializable接口,无法通过途径转换为IDisposable

class Sample<T> where T:IComparable<T>
因为将IComparable<T>整体当作约束,分析IComparable<T>的类型,可以用Type.IsValueType判断,true为值类型,false为引用类型
typeof(IComparable<T>).IsValueType 结果为false表示为引用类型
有效:Sample<int>(装箱转换)
无效:Sample<FileInfo>
也可以指定多种约束:
class sample<T> where T:stream,IEnumerable<string>,IComparable<int>
class Sample<T,U> where T:U
有效:Sample<Stream,IDisposable>
无效:Sample<string,IDiposable>
总结:要看传入类参数是否可以转换,查看规定参数和传入类参数是否实现同一接口,如果实现则可以,否则不可以。
以下不可以:System.Object,System.Enum,System.ValueType,System.Delegate,结构或密封类(String)
5.组合约束
对类型参数的约束有多个,注意:只能是一种类型,值类型和引用类型不能同时存在,没用一个类型即是引用类型,又是值类型。
类必须放到接口前面,每种参数类型分别使用一个单独的where关键字
有效:
class Sample<T> where T:class,IDisposable,new()
class Sample<T,U> where T:Stream where U:IDispsable
无效:
class Sample<T> where T:class,struct (没有任何类型即时引用类型又是值类型的,所以为无效的)
class Sample<T> where T:Stream,class (引用类型约束应该为第一个约束,放在最前面,所以为无效的) Stream只是约束传入参数为Stream具体类型,而class约束为引用类型,一开始我理解错了
class Sample<T> where T:new(),Stream (new() 必须放在最后)
class Sample<T> where T:IDisposable,Stream (类必须放在接口前面,所以为无效的)
class Sample<T> where T:XmlReader,IComparable,IComparable (对于转换类型约束,同一个接口不能出现多次)
class Sample<T,U> where T:struct where U:Class,T (类型形参“T”具有“struct”约束,因此“T”不能用作“U”的约束,所以为无效的)
class Sample<T,U> where T:Stream ,U:IDisposable 语法错误
常见泛型类型:
一、list<>
list<>即列表,list<list<double>>即double列表的列表
方法同arrarylist,链接:https://www.cnblogs.com/yaoyue68/p/14508064.html
List<int> list = new List<int>(); list.Add(1); //list[0]="dd" 这种写法不行,必须add list.Add(2); list.AddRange(new int[] { 1, 2, 3, 4, 5, 6, 7, 8 }); list.Remove(1); list.RemoveAt(1); list.Clear();
liat.removeall() foreach (var item in list) { Console.WriteLine(item); }
将list转数组 toarrary()
List<int> list = new List<int>();// int泛型,只能转int[]
list.AddRange(new int[] { 1, 2, 3, 4, 5, 6, 7 });
int[] a=list.ToArray();
使用Count方法获取List集合中特定条件的个数(Lambda)
补充方法:
list.GetRange(0, 25) ,取0-25的元素的浅复制
list.Average(), list中元素的平均值

浙公网安备 33010602011771号