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中元素的平均值

 

posted @ 2021-03-15 08:20  遥月  阅读(634)  评论(0)    收藏  举报