using System.Collections.Generic;
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;的更多相关文章
- System.Collections.Generic的各容器类的用法
演示System.Collections.Generic的各容器类的用法. 包括:Dictionary,KeyValuePair,SortedDic tionary,SortedList,HashSe ...
- NHibernate无法将类型“System.Collections.Generic.IList<T>”隐式转换为“System.Collections.Generic.IList<IT>
API有一个需要实现的抽象方法: public IList<IPermission> GetPermissions(); 需要注意的是IList<IPermission>这个泛 ...
- 无法将类型为“System.Windows.Controls.SelectedItemCollection”的对象强制转换为类型“System.Collections.Generic.IList`1
在WPF中DataGrid 选择事件中获取SelectedItems 报错如下 无法将类型为“System.Windows.Controls.SelectedItemCollection”的对象强制转 ...
- Unity3d:Unknown type 'System.Collections.Generic.CollectionDebuggerView'1
问题描述:如图,在调试状态下说:Unknown type 'System.Collections.Generic.CollectionDebuggerView'1<ignore_js_op> ...
- webservice asmx 无法序列化接口 System.Collections.Generic.IList
转载自:http://www.cnblogs.com/chenhuzi/p/4178194.html 今天有位同事在方法里加了一个IList<entity> 的返回值,也没有测试,直接发布 ...
- Web Service接口返回泛型的问题(System.InvalidCastException: 无法将类型为“System.Collections.Generic.List`1[System.String]”的对象强制转换为类型“System.String[]”)
在使用C#写Web Service时遇到了个很奇怪的问题.返回值的类型是泛型(我用的是类似List<string>)的接口,测试时发现总是报什么无法转换为对象的错误,百思不得其解. 后来在 ...
- C# 经典入门12章-System.Collections.Generic命名空间
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAtUAAAAsCAIAAAAl09PEAAAgAElEQVR4nOx95Vscyd7285cMPrg7Aw ...
- C# System.Collections.Generic.Dictionary
using System; using System.Collections.Generic; public class Example { public static void Main() { / ...
- 无法将类型“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 ...
随机推荐
- Xdebug的使用
1.http://www.cnblogs.com/mo-beifeng/articles/2446142.html 2.http://www.cnblogs.com/ximu/articles/200 ...
- 从零开始学android开发-布局中 layout_gravity、gravity、orientation、layout_weight
线性布局中,有 4 个及其重要的参数,直接决定元素的布局和位置,这四个参数是 android:layout_gravity ( 是本元素相对于父元素的重力方向 ) android:gravity (是 ...
- HDU 4819 Mosaic 二维线段树
Mosaic Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view.action ...
- java web servlet
一.什么是Servlet Servlet是一种小型的Java程序,它扩展了Web服务器的功能.作为一种服务器端的应用,他是运行在Servlet容器当中,例如Tomcat就是一种流行的Servlet容器 ...
- 安卓开发之探秘蓝牙隐藏API
上次讲解Android的蓝牙基本用法,这次讲得深入些,探讨下蓝牙方面的隐藏API.用过Android系统设置(Setting)的人都知道蓝牙搜索之后可以建立配对和解除配对,但是这两项功能的函数没有在S ...
- [原创]经历:asp.net oracle 部署问题以及解决方法
精简的美丽...... 一.环境 开发环境 win7 64bit Vs2010 Oracle 11g r2 64bit <inst ...
- bash中的数值运算
第一种,使用((表达式)): a=3 ((b=a+2)) echo $b 第二种使用let: let "c=$a+4" echo $c 第三种,使用expr表达式(注意空格不能少) ...
- Wireshark抓包工具使用教程以及常用抓包规则
转载:http://fangxin.blog.51cto.com/1125131/735178 Wireshark是一个非常好用的抓包工具,当我们遇到一些和网络相关的问题时,可以通过这个工具进行分析, ...
- PHP.2-LAMP平台介绍及网站的工作原理
LAMP平台介绍及网站的工作原理 1.HTTP协议 URL(UniformResourceLocator)统一资源定位符,就是网页地址的意思.[格式:协议://主机.端口.文件.附加资源] ##URL ...
- SpringMVC的简单示例
首先导入所需的jar包,项目目录结构如下: 之后需要配置一下web.xml文件,内容如下: <?xml version="1.0" encoding="UTF-8& ...