一、定义泛型类

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. ubuntu18.04下安装gitlab

    1.安装并配置必要的依赖关系 sudo apt-get update sudo apt-get install -y curl openssh-server ca-certificates 接下来,安 ...

  2. mysql You can't specify target table for update in FROM clause解决方法

    mysql You can't specify target table for update in FROM clause解决方法出现这个错误的原因是不能在同一个sql语句中,先select同一个表 ...

  3. QT QML之Label, TextField

    现在不是去想缺少什么的时候,该想一想凭现有的东西你能做什么.------ 海明威 <老人与海> Label { id: tipLabel width: 120 height: 40 tex ...

  4. QT中PRO文件解析(转)

    From csdn blog: QT中PRO文件写法的详细介绍,很有用,很重要! 在QT中,有一个工具qmake可以生成一个makefile文件,它是由.pro文件生成而来的,.pro文件的写法如下: ...

  5. LocalDate LocalTime LocalDateTime Instant的操作与使用

    一.简介 LocalDate表示当前(或指定)日期,格式为:yyyy-MM-dd LocalTime表示当前(或指定)时间,格式为:HH:mm:ss SSS LocalDateTime表示当前(或指定 ...

  6. struts下载文件错误,想不明白为什么更改变量名就不报错了

    java.lang.IllegalArgumentException: Can not find a java.io.InputStream with the name [is] in the inv ...

  7. 如何利用 iTunes 把 m4a/wav 文件转成 MP3 格式

    MAC技巧 | 如何利用 iTunes 把 m4a/wav 文件转成 MP3 格式 - 简书

  8. PB笔记之日期函数

    https://wenku.baidu.com/view/a0d5f16fb84ae45c3b358cc7.html this.object.yjzzrq[row]= RelativeDate(dat ...

  9. Mysql union和union all用法

    1: 什么时候用union和union all ?    我们经常会碰到这样的应用,两个表的数据按照一定的查询条件查询出来以后,需要将结果合并到一起显示出来,这个时候 就需要用到union和union ...

  10. Python 内置函数进制转换的用法(十进制转二进制、八进制、十六进制)

    使用Python内置函数:bin().oct().int().hex()可实现进制转换. 先看Python官方文档中对这几个内置函数的描述: bin(x)Convert an integer numb ...