一、定义泛型类

void Main()
{
//实例化泛型类时,才指定具体的类型
MyGenericClass<int> MyGeneri = new MyGenericClass<int>();
Console.WriteLine(MyGeneri.InnerT1Object * );
} public class MyGenericClass<T>//<T1,T2,T3>表示多个类型参数
{
private T innerT1Object;
public string LastName;
public MyGenericClass(T item)//构造函数
{
this.innerT1Object = item;
}
public T InnerT1Object//泛型属性
{
get { return innerT1Object; }
}
}

注意:

1、不能假定T提供了什么类型。eg:innerT1Object=new T(),因为T可能根本无公共默认构造函数。除非 class MyGenericClass<T> where T:new()

public class MyGenericClass<T> where T : new()
{
private T innerT1Object = new T();
}

2、可以把T看作继承System.Object的类型:typeof(T),T.ToString()

3、在没有指定约束类型参数的情况下,比较泛型类型值和null,只能使用==或!=。不能对两个类型值变量进行比较。

public bool Compare(T op1, T op2)
{
if (op1 != null && op2 == null)//正确。如果T为值类型,op1!=null始终成立。
{
//…
}
if (op1 == op2)//错误,因为这就假定了T支持==运算符
{
//…
}
}

4、default关键字用于为T赋默认值,而无需考虑其实值类型还是引用类型。

public class MyGenericClass<T>
{
private T innerT1Object = default(T);
}

5、where 关键字用于约束T的类型。

class MyGenericClass<T> where T:Animal

可用的约束有:

  • struct :值类型
  • class:引用类型
  • <baseclass>:此列或者此类的派生类
  • <interface>:此接口或者实现此接口
  • new():必须具有无参数的公共构造函数。必须为类型的最后得约束。
  1. 一个类型参数可有多个约束:class Myclass<T> where T: constait1,constrait2
  2. 各类型参数不同的约束:class Myclass<T1,T2> where T1: constait1,T2:constrait2
  3. 约束放于继承符之后:class Myclass<T1>:MyBaseCalss,IMyInterface  where T: constait
  4. 一个类型参数用作另一个类型参数的约束,表示T2与T1的类型相同,或T2继承于T1(裸类型约束)class Myclass<T1,T2> where T2: T1

6、泛型类的静态成员只能在类的一个实例中共享:

void Main()
{
StaticDemo<string>.x=;
StaticDemo<int>.x=;
} public class StaticDemo<T>
{
public static int x;
}

二、从泛型类继承

1、泛型类至少与基类有相同的约束,或为基类的子集

public class Farm<T> where T : Animal
{
//...
} public class SuperFarm<T> : Farm<T> where T : SuperCow //SuperCow为Animal的子集
{
//...
}

2、类继承泛型,必须提供所有的类型信息

public class Cards : List<Card> //派生非泛型
{ }

三、定义泛型运算符

public static Farm<T> operator +(Farm<T> farm1, Farm<T> farm2)
{ }

四、定义泛型结构

public struct MyStruct<T1, T2>
{
public T1 item1;
public T2 item2;
}

五、定义泛型接口

interface myInterface<T> where T : Animal
{
bool Brea(T animal1, T animal2);
T oldest { get; }
}

实例:

public interface IComparable<T>
{
int CompareTo(T other);
} public class Person : IComparable<Person>
{
public int CompareTo(Person other)
{
return this.name.CompareTO(other.name);
}
}

六、定义泛型方法

1、普通类

public class Defaulter
{
public T GetDefault<T>()
{
return default(T);
}
}

2、泛型类

public class Defaulter<T1>
{
public T2 GetDefault<T2>() where T2 : T1 //泛型方法的参数最好不要与其所在的泛型类的类型参数相同
{
return default(T2);
} public void Process()
{
}
public void Process<T>(T1 op1)//重载方法1
{
} public void Process<T, U>(T1 op1)//重载方法2
{
}
}

七、定义泛型委托

1、通过泛型委托,委托的参数可以在以后定义。

public delegate T1 MyDelegate<T1, T2>(T2 op1, T2 op2) where T1 : T2;

2、常用内置委托:

(1)、Action<T>: 泛型委托。无返回值。 委托的方法可以有1-16个输入参数。Action:无参数无返回值委托。

Action action1 = () => Console.Write("a");
action1(); Action<string> action2 = (p) => Console.Write(p);
action2("b");

利用Action实现线程和界面交互:

private void button1_Click(object sender, EventArgs e)
{
WaitCallback waitCallBack = new WaitCallback(this.AlternationUsingAction);
ThreadPool.QueueUserWorkItem(waitCallBack, "Action的使用");
} private void AlternationUsingAction(object text)
{
this.Invoke((Action)( () =>
{
button1.Text = text.ToString();
} ));
}

(2)、Func<T>:必须具有返回值。委托的方法可以有0-16个参数输入参数,加一个输出参数。

Func<int, int, string > Func = (a, b) => (a + b).ToString();
Console.Write(Func(1, 2));

(3)、Predicate<T>:就是只接受一个传入参数,返回值为bool类型。

用于搜索方法

public delegate bool Predicate<T>(T obj);//判断条件函数
public T Find(Predicate<T> matach);

举例:


Predicate<string[]> predicate = x =>
{
var result = from p in x
where p.Contains("s")
select p;
return result.ToList().Count > 0; };
string[] _value = { "charlies", "nancy", "alex", "jimmy", "selina" };
Console.WriteLine(predicate(_value) ? "包含." : "不包含");

(4)、Comparision<T>(T obj1,T obj2):比较函数,用于搜索方法。

public delegate int Comparision<T>(T obj1,T obj2)//
public void Sort(Comparision<T> comprison)

(5)、EventHandler<TEventArgs>:泛型事件处理函数。

public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e) where TEventArgs : EventArgs;

3、实例:

public delegate TSummary Action<TInput, TSummary>(TInput t, TSummary u);//定义泛型委托
public static TSummary Accumulate<TInput, TSummary>(IEnumerable <TInput> cols, Action<TInput, TSummary> action)
//将委托实例action传给方法参数。
{
TSummary sum = default(TSummary);
foreach (TInput input in cols)
{
sum = action(input, sum);//执行委托方法
}
return sum;
} void Main()
{
decimal amount = Accumulate<int, decimal>(new List<int> { , }, (a, b) => a + b);//(a, b) => a + b为委托实例
Console.Write(amount);
}

八、定义泛型事件

事件与委托就像一对孪生兄弟。既然有泛型委托,那么也应该有泛型事件。因为在以前,事件处理函数的发送方参数的类型总是Object。因此事件处理函数没有办法根据不同的发送者身份或者类型对事件进行不同的处理。现在如果使用泛型事件就可以使用强类型的发送方,不再需要强制转换成Object或反向强制转换。而且也可以根据发送方类型的不同对消息进行不同的处理。

例子中演示了发送方是强类型的情况,在这个例子中使用泛型类Publisher<T>来表示消息的发布者,用类Receiver来表示消息的订阅者。

//定义了一个泛型委托,该委托指定了发送者的具体类型
public delegate void MyEventHandler<T>(Publisher<T> Sender); void Main()
{
//事件发布者
Publisher<int> publisherI = new Publisher<int>();
Publisher<double> publisherD = new Publisher<double>(); //事件订阅者
Receiver receiver = new Receiver(); //开始绑定事件
publisherI.Click += receiver.OnClick;
publisherD.Click += receiver.OnClick; //引发事件
publisherI.SendMessage();
publisherD.SendMessage();
} //消息发布者类Publisher<T>的代码
public class Publisher<T>
{
//定义了一个泛型事件,该事件的发布者的类型是强类型
public event MyEventHandler<T> Click; //发送事件函数
public void SendMessage()
{
Click(this);
}
} //消息订阅者类Receiver的代码
class Receiver
{
//事件处理函数,该函数具有强类型的参数表示发送者
public void OnClick(Publisher<int> sender)
{
Console.WriteLine("该事件已经写入日志文件");
} //事件处理函数
public void OnClick(Publisher<double> sender)
{
Console.WriteLine("该事件已经发送到主管信箱");
}
}

九、可空类型System.Nullable<T>

1、声明和赋值

Nullable<int> x = ;//可写成int? x = 4
x = null;//可为可空类型赋值null.

2、判断为空

int y;
if (x.HasValue)//或者x!=null
{
y = x = value;
}
else
{
y = x ?? ;//或者 x.GetValueOrDefault(); x=null则或者其默认值。
}

3、转换

int? op1=;
int? result=op1 *; int? op2=;
int result1=op2 *;//如果op2为null,强制转换int?到int产生异常

十、ArraySegement<T> 数组片段

int[] arr = { , , , , , , ,  };
ArraySegment<int> segment = new ArraySegment<int>(arr, , );
for (int i = segment.Offset; i < segment.Offset + segment.Count; i++)
{
Console.WriteLine(segment.Array[i]);
}

泛型 System.Collections.Generic及泛型继承、运算符、结构、接口、方法、委托、事件、可空类型等的更多相关文章

  1. C#:system.collections.generic(泛型)

    1. array是一个固定长度的,如果要动态的存储的话就不行了,虽然 System.Collections.ArrayList(),是一个动态的存储的容器,但是没有对存储中的数据进行一个约束,所以非泛 ...

  2. using System.Collections.Generic;

    public class CommonClass { public static void ShowInt(int iValue) { //typeof(CommonClass) typeof关键字 ...

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

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

  4. 无法将类型“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 ...

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

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

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

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

  7. C# System.Collections.Generic.Dictionary

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

  8. System.Collections.Generic.List<T> 与 System.Collections.ArrayList

    [推荐] System.Collections.Generic.List<T> [原因] 泛型集合类List<T>在操作值类型的集合时可以不进行 装箱/拆箱 处理. 使得性能较 ...

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

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

随机推荐

  1. [C++] 习题 2.15 实现简单环形队列

    目录 前置技能 环形队列 具体实现 设计一个环形队列,用front和rear分别作为队头和队尾指针,另外用一个tag表示队列是空 ( 0 ) 还是不空 ( 1 ),这样就可以用front==rear作 ...

  2. python 之 subprocesss 模块、configparser 模块

    6.18 subprocesss 模块 常用dos命令: cd : changedirectory 切换目录 ​ tasklist:查看任务列表 ​ tasklist | findstr python ...

  3. BC26模组UDP调试

    BC26模组调试 数据上报AT流程 [15:33:46.819]收←◆ F1: 0000 0000 V0: 0000 0000 [0001] 00: 0006 000C 01: 0000 0000 U ...

  4. 知识不是来炫耀的,而是来分享的-----现在的人们却…似乎开始变味了…

    我讨厌那些自以为是的人,哪些只有远大抱负却不付出的混蛋,我讨厌那些老生欺负小生,讨厌以大欺小,讨厌别人把知识拿来炫耀. 我自己也不愿做这类人,我渴望看到成功,我不怕一意孤行,我不怕失败,我只怕自己做的 ...

  5. 【统计与建模】R语言基本操作

    # vec <- rep( seq(1,5,by=0.5),3) # vec <- seq( 1 , 10 , by = 1 ) # min(vec) #最小值 # max(vec) #最 ...

  6. H5中表格的用法

    1.表格的基本结构: 表格由行和列组成,单元格式表格的最基本单元;每个表格均有若干行,行标签由<tr></tr>定义,每行被分割为若干单元格,由<td></t ...

  7. 音视频入门-09-RGB&YUV互转-使用开源库

    * 音视频入门文章目录 * 介绍开源库 使用第三方开源库来简化开发,屏蔽一些底层的复杂度,节省大量编写代码的时间. libyuv: Google 开源的实现各种 YUV 与 RGB 之间相互转换.旋转 ...

  8. IIS发布问题解决

    一. HTTP Error 502.5 - ANCM Out-Of-Process Startup Failure ://安装AspNetCoreModule托管模块后执行1. net stop wa ...

  9. Python——pip的安装与使用

    pip 是 Python 包管理工具,该工具提供了对Python 包的查找.下载.安装.卸载的功能.目前如果你在 python.org 下载最新版本的安装包,则是已经自带了该工具.Python 2.7 ...

  10. Java 之 文件过滤器

    在学习过滤器之前,先来做一个案例. 题目:文件搜索,搜索 D:\java 目录中 .java 文件. 分析: 1.  目录搜索,无法判断多少级目录,使用递归,遍历所有目录 2.  遍历目录时,获取的子 ...