public class CommonClass
     {
         public static void ShowInt(int iValue)
         {
             //typeof(CommonClass) typeof关键字 获取一个类型的类型
             Console.WriteLine(" ShowInt方法 展示{0},其类型为{1}", iValue, typeof(int));
         }

         public static void ShowLong(long lValue)
         {
             //lValue.GetType() 变量.GetType()  获取一个变量的类型
             Console.WriteLine(" ShowLong方法 展示{0},其类型为{1}", lValue, lValue.GetType());
         }

         public static void ShowString(string sValue)
         {
             Console.WriteLine(" ShowString方法 展示{0},其类型为{1}", sValue, sValue.GetType());
         }

         public static void ShowDateTime(DateTime dValue)
         {
             Console.WriteLine(" ShowDateTime方法 展示{0},其类型为{1}", dValue, dValue.GetType());
         }

         /// <summary>
         /// 1 通过继承,子类拥有父类的一切属性和行为,任何父类出现的地方,子类都可以代替
         /// 2 object 类型是一切类型的父类
         /// </summary>
         /// <param name="oValue"></param>
         public static void ShowObject(object oValue)
         {
             Console.WriteLine(" ShowObject方法 展示{0},其类型为{1}", oValue, oValue.GetType());
         }
     }

每种方法都需要声明一个,作为一名程序员都知道这样是不对的,效率太低。

但是用object类型则需要多次的装箱和拆箱操作,效率上实在是不太好了。

所以有了泛型,泛型就是先不声明类型,用占位符替代类型的位置,在使用的时候再指定类型。

下面引入泛型:

通过一个方法完成多个不同参数类型的方法-泛型方法

1        /// <summary>
         /// 延迟声明:推迟一切可以推迟的东西
         /// </summary>
         /// <typeparam name="T"></typeparam>
         /// <param name="tValue"></param>
         public static void Show<T>(T tValue)//Show`1   1是泛型类型的个数
         {
             Console.WriteLine(" Show<T>方法 展示{0},其类型为{1}", tValue, tValue.GetType());
         }

基础类:

    public class BaseModel
     {
         public int Id { get; set; }
         public string Name { get; set; }
     }

     public class People : BaseModel
     {
         public void SayHi()
         {
             Console.WriteLine("{0} 吃了吗", base.Name);
         }
     }

     public class Chinese : People, ISport,IGame
     {
         public string Majiang { get; set; }

         public void Pingpang()
         {
         }

         public void Yumao()
         {
         }

         public void Chess()
         {
         }
     }

     public class Japanese
     {
         public int Id { get; set; }
         public string Name { get; set; }
         public void SayHi()
         {
             Console.WriteLine("{0} ^*^&^&%&", this.Name);
         }
         public string Dongman { get; set; }
     }

     public interface ISport
     {
         void Pingpang();
         void Yumao();
     }

     public class Sporter : ISport
     {

         public void Pingpang()
         {

         }

         public void Yumao()
         {
         }
     }

     public interface IGame
     {
         void Chess();
     }
1         泛型里的<>占位符可以多个,指定占位符后可以在本方法内使用占位符所代表的类型,比如现在参数列表里      声明变量,然后再使用(占位符不一定要使用完,就像我有钱,并不一定要花完一样.)       

           private static void Test<T, S, RUANMOU, Eleven>(T tValue, Eleven eleven)//Test`4
         {
             Console.WriteLine(" Show<T>方法 展示{0},其类型为{1}", tValue, tValue.GetType());
         }

泛型接口:

     public interface IGenericInterface<T, S, W, Ruanmou>
     {
         void Query<X, Y, T, S>();
         void Do(T t);
     }
    public interface IInterface
     {
         void Foo();
     }

声明泛型类的可能遇到的两种情况

1 参数列表要和继承的保持一致,继承者的参数列表可以多但不能比被继承的参数少.

    public class ClassFromInterface<T, S, W, Ruanmou,liuyJ> : IInterface, IGenericInterface<T, S, W, Ruanmou>
     {

         public void Foo()
         {
             throw new NotImplementedException();
         }

         public void Query<X, Y, T, S>()
         {
             throw new NotImplementedException();
         }

         public void Do(T t)
         {
             throw new NotImplementedException();
         }
     }

2.在继承的泛型接口里直接指定类型

  public class ClassFromInterfaceCommon : IInterface, IGenericInterface<int, string, DateTime, IInterface>
     {

         public void Foo()
         {
             throw new NotImplementedException();
         }

         public void Query<X, Y, T, S>()
         {
             throw new NotImplementedException();
         }

         public void Do(int t)
         {
             throw new NotImplementedException();
         }
     }

泛型约束:享受约束,拥有权力.

      /// <summary>
         /// 基类约束是第一个,而且只能有一个People
         /// 接口约束可以多个 ISport,IGame
         /// 值类型和引用类型约束本身不能共存,,而且有了基类约束后,也不需要二者
         /// new只能放在最后面
         /// </summary>
         /// <typeparam name="T"></typeparam>
         /// <param name="tValue"></param>
         public static void Show<T>(T tValue)
             where T : People, ISport, IGame, new()
         {
             System.Console.WriteLine(tValue.Name);
             System.Console.WriteLine(tValue.Id);
             tValue.SayHi();

             tValue.Pingpang();
             tValue.Yumao();

             tValue.Chess();

             T t = new T();

             Console.WriteLine(" Show<T>方法 展示{0},其类型为{1}", tValue, tValue.GetType());
         }

对比以下两个方法,一个是泛型方法,另一个是去掉泛型<>,直接指定People.

      public static void ShowPeople<T>(T tValue)
             where T : People
         {
             System.Console.WriteLine(tValue.Name);
             System.Console.WriteLine(tValue.Id);
             tValue.SayHi();

             Console.WriteLine(" Show<T>方法 展示{0},其类型为{1}", tValue, tValue.GetType());
         }

         public static void ShowPeople(People tValue)
         {
             System.Console.WriteLine(tValue.Name);
             System.Console.WriteLine(tValue.Id);
             tValue.SayHi();

             Console.WriteLine(" Show<T>方法 展示{0},其类型为{1}", tValue, tValue.GetType());
         }

从这里就看出了约束的作用了,使用它的类型必须是People类型或者它的子类.

任何父类出现的地方都可以用子类来替代.

class和struct约束

        private T Get<T>()
             //where T : class//表示T是引用类型
             //where T : struct//表示T是值类型
             where T : new()//表示T有一个无参数的构造函数
         {
             T t = new T();
             return default(T);
         }

接口约束:

        public static void ShowPeopleInterface<T>(T tValue)
             where T : ISport
         {
             tValue.Yumao();
             tValue.Pingpang();

             Console.WriteLine(" Show<T>方法 展示{0},其类型为{1}", tValue, tValue.GetType());
         }

协变out--修饰返回值--子到父.   |     逆变in--修饰传入参数值--父到子.

主要用在泛型接口和泛型委托上

基本类,后面会用到:

     public class Parent
     {
         public int Id { get; set; }
     }
     public class Child : Parent
     {
         public string Name { get; set; }
     }

in和out的接口

     public interface ICustomerListIn<in T>
     {
         void Show(T t);//使用传入参数
     }

     public interface ICustomerList<out T>
     {
         T Get();//返回
     }

接口继承:

out

     public interface ICustomerList<out T>
     {
         T Get();
     }

     public class CustomerList<T> : ICustomerList<T>
     {
         public T Get()
         {
             return default(T);
         }
     }

in

     public interface ICustomerListIn<in T>
     {
         void Show(T t);
     }

     public class CustomerListIn<T> : ICustomerListIn<T>
     {
         public void Show(T t)
         {
         }
     }

----------------------------------------------------------那么正题来了-----------------------------------------------------------------------------------------------------------

1. 一般情况下,子类可以初始化基类,但是,基类是不可以初始化子类的.

           {
                 Parent parent1 = new Parent();
                 Parent parent2 = new Child();
                 Child child1 = new Child();
                 //Child child2 = new Parent();---报错了哦!
             }    

儿子以后可以当老子,老子却不能当儿子(这里只说父子,没有爷爷.)

2. 初学者的误区:在List<>里面指定父类和子类

        比如:Parent和Child有继承和派生的关系,但是,并不代表着List<Parent>和List<Child>有半毛钱的关系.

           因为List<Parent>和List<Child>分别是新的类型而且是不同的List<泛型集合>类型.

       {
                List<Parent> parentList1 = new List<Parent>();
                //List<Parent> parentList2 = new List<Child>();//ParentList类型和ChildList类型没有父子关系,所以即使Perent和Child有父子关系也不能这么玩
                List<Parent> parentList3 = new List<Child>().Select(c => (Parent)c).ToList();
            }

3.添加有out的就可以咯

 namespace System.Collections.Generic
 {
     // 摘要:
     //     公开枚举数,该枚举数支持在指定类型的集合上进行简单迭代。
     //
     // 类型参数:
     //   T:
     //     要枚举的对象的类型。
     [TypeDependency("System.SZArrayHelper")]
     public interface IEnumerable<out T> : IEnumerable
     {
         // 摘要:
         //     返回一个循环访问集合的枚举器。
         //
         // 返回结果:
         //     可用于循环访问集合的 System.Collections.Generic.IEnumerator<T>。
         IEnumerator<T> GetEnumerator();
     }
 }

系统的协变out

        {
                 IEnumerable<Parent> parentList1 = new List<Parent>();
                 IEnumerable<Parent> parentList2 = new List<Child>();//ParentList类型和ChildList类型没有父子关系
             }

4. out-子到父-协变

        {
                 ICustomerList<Parent> customerList1 = new CustomerList<Parent>();
                 ICustomerList<Parent> customerList2 = new CustomerList<Child>();
             }
 

5.in-父到子-逆变

 1         {
                 ICustomerListIn<Child> customerList2 = new CustomerListIn<Child>();
                 customerList2.Show(new Child());

                 ICustomerListIn<Child> customerList1 = new CustomerListIn<Parent>();
                 customerList1.Show(new Child());

                 ICustomerListIn<Parent> parentList1 = new CustomerListIn<Parent>();
                 parentList1.Show(new Child());
                 parentList1.Show(new Parent());
             }

6.out和in都有的情况,都可以咯.

    public class MyList<T1, T2> : IMyList<T1, T2>
     {

         public void Show(T1 t)
         {
             Console.WriteLine(t.GetType().Name);
         }

         public T2 Get()
         {
             Console.WriteLine(typeof(T2).Name);
             return default(T2);
         }

         public T2 Do(T1 t)
         {
             Console.WriteLine(t.GetType().Name);
             Console.WriteLine(typeof(T2).Name);
             return default(T2);
         }
     }
     public interface IMyList<in inT, out outT>
     {
         //out 只能是返回值   in只能是参数
         void Show(inT t);
         outT Get();
         outT Do(inT t);
     }

总体来说:  out和in的功能就是告诉编译器不报错.

out,是协变嘛,协助变换,顺向的,就是子类到父类.所以可以返回.

但不能当参数用,因为子类变父类是有限制的.

in,是逆变呗,逆向变换,逆向的,就是父类到子类.只能用在参数里.

讲道理,它是违规的,所以呢,不能返回,当参数运算还是可以得.

using System.Collections.Generic;的更多相关文章

  1. System.Collections.Generic的各容器类的用法

    演示System.Collections.Generic的各容器类的用法. 包括:Dictionary,KeyValuePair,SortedDic tionary,SortedList,HashSe ...

  2. NHibernate无法将类型“System.Collections.Generic.IList<T>”隐式转换为“System.Collections.Generic.IList<IT>

    API有一个需要实现的抽象方法: public IList<IPermission> GetPermissions(); 需要注意的是IList<IPermission>这个泛 ...

  3. 无法将类型为“System.Windows.Controls.SelectedItemCollection”的对象强制转换为类型“System.Collections.Generic.IList`1

    在WPF中DataGrid 选择事件中获取SelectedItems 报错如下 无法将类型为“System.Windows.Controls.SelectedItemCollection”的对象强制转 ...

  4. Unity3d:Unknown type 'System.Collections.Generic.CollectionDebuggerView'1

    问题描述:如图,在调试状态下说:Unknown type 'System.Collections.Generic.CollectionDebuggerView'1<ignore_js_op> ...

  5. webservice asmx 无法序列化接口 System.Collections.Generic.IList

    转载自:http://www.cnblogs.com/chenhuzi/p/4178194.html 今天有位同事在方法里加了一个IList<entity> 的返回值,也没有测试,直接发布 ...

  6. Web Service接口返回泛型的问题(System.InvalidCastException: 无法将类型为“System.Collections.Generic.List`1[System.String]”的对象强制转换为类型“System.String[]”)

    在使用C#写Web Service时遇到了个很奇怪的问题.返回值的类型是泛型(我用的是类似List<string>)的接口,测试时发现总是报什么无法转换为对象的错误,百思不得其解. 后来在 ...

  7. C# 经典入门12章-System.Collections.Generic命名空间

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAtUAAAAsCAIAAAAl09PEAAAgAElEQVR4nOx95Vscyd7285cMPrg7Aw ...

  8. C# System.Collections.Generic.Dictionary

    using System; using System.Collections.Generic; public class Example { public static void Main() { / ...

  9. 无法将类型“System.Collections.Generic.List<anonymous type:string ClassID,string ClsssName>”隐式转换为“System.Collections.Generic.List<Ecology.Model.EnergyFlowGraph>”

    无法将类型“System.Collections.Generic.List<anonymous type:string ClassID,string ClsssName>”隐式转换为“Sy ...

随机推荐

  1. 教你50招提升ASP.NET性能(二十二):利用.NET 4.5异步结构

    (40)Take advantage of .NET 4.5 async constructs 招数40: 利用.NET 4.5异步结构 With the arrival of .NET 4.5, w ...

  2. 一种基于Welch's t检验的二元关系挖掘

    现实中常常需要挖掘两种因素之间的关联,Welch's t检验很适合其中的nomial-numerical的关系挖掘.比如天气状况对销量的影响,或者天气情况对交通流量的影响等等.我们可以按照下雨/不下雨 ...

  3. centos环境配置

    1. centos上安装开发环境 yum groupinstall "Development Tools" "Legacy Software Development&qu ...

  4. XSS攻击:SOHU视频XSS漏洞导致其用户成为DDOS肉鸡

    XSS又叫CSS (Cross Site Script) ,跨站脚本攻击.恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入当中Web里面的html代码会被运行,从而达到恶意攻击用 ...

  5. python的一些总结5

    上面4都是水的 恩每篇都一点知识点 用来写给不耐烦的人看..哈哈这篇 争取不水. 上面4篇如果 掌握 基本上是 80%常用的代码了. 1.下面讲一下 比较常用的代码: macro(jinja 上的功能 ...

  6. POJ 2406 Power Strings KMP运用题解

    本题是计算一个字符串能完整分成多少一模一样的子字符串. 原来是使用KMP的next数组计算出来的,一直都认为是能够利用next数组的.可是自己想了非常久没能这么简洁地总结出来,也仅仅能查查他人代码才恍 ...

  7. memset用法详解(转)

    问题描述: int * cow = new int[n+1]; memset(cow,0,(n+1)*4); 将N+1个元素置成0,为什么不行 memset是对一个字节的int4个字节,因此*4 但是 ...

  8. Spring MVC 接收Json格式参数

    今天做了一个关于表格排序的功能,可以通过右边的箭头做排序操作,每次操作需要通过Ajax将每条记录的Id数组作为参数去发送请求, 后台Spring MVC接到参数后作更改序号操作. 前端页面发送请求的代 ...

  9. SQL SERVER 函数大全[转]

    SQL Server 函数大全 一旦成功地从表中检索出数据,就需要进一步操纵这些数据,以获得有用或有意义的结果.这些要求包括:执行计算与数学运算.转换数据.解析数值.组合值和聚合一个范围内的值等. 下 ...

  10. Linux中errno使用 - [Linux]

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明http://www.blogbus.com/wzgyantai-logs/24470871.html 当linux中的C api函数发 ...