邯郸移动网站建设价格,个人网站域名所有权,wampserver集成环境搭建了一个织梦cms网站,seo优化推广工程师本讲用许多代码示例介绍了 C# 语言当中的泛型#xff0c;主要包括泛型类、接口、结构、委托和方法。 文章目录 1. 为什么需要泛型#xff1f;2. 泛型类的定义2.1 泛型类的定义2.2 使用泛型类创建变量和实例 3. 使用泛型类实现一个简单的栈3.1 类型参数的约束3.2 Where 子句3…本讲用许多代码示例介绍了 C# 语言当中的泛型主要包括泛型类、接口、结构、委托和方法。 文章目录 1. 为什么需要泛型2. 泛型类的定义2.1 泛型类的定义2.2 使用泛型类创建变量和实例 3. 使用泛型类实现一个简单的栈3.1 类型参数的约束3.2 Where 子句3.3 约束类型和次序 4. 泛型方法5. 泛型结构6. 泛型委托7. 泛型接口 1. 为什么需要泛型
在之前的教程中我们使用的自定义类都是具有具体的类型。如果对类型进行抽象该类型就是泛型即一种广泛的类型。例如我们有一个水果篮水果篮中可以放不同种类的水果例如苹果、香蕉、菠萝等等。这个水果篮可以放置的水果就是一种泛型水果可以代指很多不同种类的水果。
为什么需要泛型泛型的好处之一就是能够提高代码的复用性。例如我们有一种栈数据结构栈当中的类型可以是 int、float等等但很多操作都是相同的入栈、出栈、获取栈大小所不同的是数据类型的不同。利用泛型我们只需要实现一套代码而不需要针对不同的数据类型分别实现各自的一套栈代码。
在 C# 中泛型又称为参数化类型。泛型可以作用在类、函数、结构、委托和接口由此衍生出泛型类、泛型函数、泛型结构、泛型委托和泛型接口的概念。
2. 泛型类的定义
2.1 泛型类的定义 2.2 使用泛型类创建变量和实例
在使用泛型类创建变量时可以使用关键字 var让编译器根据 右边的类型自动推断变量的类型。
using System;class SomeClassT1, T2
{public T1 Property1 { get; set; }public T2 Property2 { get; set; }// Constructorpublic SomeClass(T1 property1, T2 property2){Property1 property1;Property2 property2;}
}
class Program
{static void Main(string[] args){SomeClassint, float sc new SomeClassint, float(10, 3.14f);var sc2 new SomeClassstring, bool(Hello, true); // 让编译器推断类型Console.WriteLine(sc.Property1);Console.WriteLine(sc.Property2);Console.WriteLine(sc2.Property1);Console.WriteLine(sc2.Property2);}
}输出
10
3.14
Hello
true需要注意的是为具体类分配的内存是存储在堆上的。
3. 使用泛型类实现一个简单的栈
using System;namespace GenericStackExample
{// 定义一个泛型栈类 public class StackT{// 使用数组来存储栈中的元素 private T[] _items;// 栈顶元素的索引初始化为-1表示栈为空 private int _top;// 栈的容量 private int _capacity;// 构造函数初始化栈的容量 public Stack(int capacity 10){_capacity capacity;_items new T[capacity];_top -1;}// 检查栈是否为空 public bool IsEmpty(){return _top -1;}// 检查栈是否已满 public bool IsFull(){return _top _capacity - 1;}// 入栈操作 public void Push(T item){if (IsFull()){throw new InvalidOperationException(Stack is full.);}_items[_top] item;}// 出栈操作 public T Pop(){if (IsEmpty()){throw new InvalidOperationException(Stack is empty.);}return _items[_top--];}// 查看栈顶元素不移除 public T Peek(){if (IsEmpty()){throw new InvalidOperationException(Stack is empty.);}return _items[_top];}// 获取栈的大小元素数量 public int Size(){return _top 1;}}class Program{static void Main(string[] args){Stackint intStack new Stackint(5); // 创建一个整型栈 // 入栈操作 intStack.Push(1);intStack.Push(2);intStack.Push(3);// 访问栈顶元素 Console.WriteLine($栈顶元素是: {intStack.Peek()});// 出栈操作 Console.WriteLine($出栈元素: {intStack.Pop()});// 获取栈的大小 Console.WriteLine($栈的大小是: {intStack.Size()});// 尝试在空栈上执行出栈操作以演示异常 try{intStack.Pop();}catch (InvalidOperationException ex){Console.WriteLine(ex.Message);}}}
}
3.1 类型参数的约束
现在我们能够设计出泛型类但是泛型类型它本身提供什么方法我们是不知道的。例如下面的泛型类
class SimpleT
{static public bool LessThan(T i1, T i2){return i1 i2;}
}
...但不是所有类型 T 都实现了小于运算符所以会报出错误 为此我们需要告诉编译器关于泛型类型的额外信息让其知道参数可以接受哪些类型。这些额外的信息叫做约束constrain。没有任何约束的类型参数称为未绑定的类型参数unbounded type parameter。
3.2 Where 子句
约束使用 where 子句列出
3.3 约束类型和次序
共有 5 种类型的约束如下表所示
约束类型描述某个具体的类名只有这个类型的类或从它继承的类才能用作类型参数class任何引用类型包括类、数组、委托和接口都可以用作类型参数struct任何值类型都可以用作类型参数接口名只有这个接口或实现这个接口的类型才能用作类型参数new()任何带有无参公共构造函数的类型都可以用作类型参数。这叫做构造函数约束
对不同类型的 where 约束可以以任何顺序列出。但是where 子句内的约束必须遵循一定的顺序
最多只能具有一个主约束有的话必须放到第一位可以有任意多的接口名约束如果存在构造函数约束则必须放到最后。 下面是一些例子
class SortedListSwhere S: IComparableS
{ }class LinkedListM, Nwhere M: IComparableMwhere N: ICloneable
{ }class MyDictionaryKeyType, ValueTypewhere KeyType: IComparableKeyType,new()
{ }4. 泛型方法
泛型方法的定义如下
泛型方法的使用
void DoStuffT1, T2 (T1 t1, T2 t2)
{T1 someVar t1;T2 otherVar t2;
}DoStuffint, string(10, Hello);
DoStuffint, long(iVal, lVal);当参数类型列表的类型和方法列表中的类型相同时在使用泛型方法时可以省略对参数类型的指定例如
public void MyMethodT (T val) {}
int myInt 5;
MyMethod(myInt);泛型方法的使用示例
class Simple
{static public void ReverseAndPrintT(T[] arr){Array.Reverse(arr);foreach (var item in arr){Console.Write({0}, , item.ToString());Console.WriteLine();}}
}class Program
{static void Main(){// 创建整数、字符串、浮点型数组 int[] intArray { 1, 2, 3, 4, 5 };string[] stringArray { hello, world };float[] floatArray { 1.1f, 2.2f, 3.3f };// 调用泛型方法反转并打印数组 Simple.ReverseAndPrint(intArray);Simple.ReverseAndPrintint(intArray);Simple.ReverseAndPrint(stringArray);Simple.ReverseAndPrintstring(stringArray);Simple.ReverseAndPrint(floatArray);Simple.ReverseAndPrintfloat(floatArray);}
}输出结果
5. 泛型结构
泛型结构和泛型类的定义类似直接给出例子。
struct PieceOfDataT
{public T _data { get; set; }public PieceOfData(T data){_data data;}
}class Program
{static void Main(){PieceOfDataint piece1 new PieceOfDataint(10);PieceOfDatastring piece2 new PieceOfDatastring(Hello);Console.WriteLine(piece1._data);Console.WriteLine(piece2._data);}
}6. 泛型委托 委托类型当中可以使用泛型的地方
返回类型类型参数where子句
泛型委托的例子
delegate void MyDelegateT(T value);class Simple
{static public void PrintString(string s){Console.WriteLine(s);}static public void PrintUpperString(string s){Console.WriteLine(s.ToUpper());}
}class Prgram
{static void Main(){MyDelegatestring d1 new MyDelegatestring(Simple.PrintString);d1 Simple.PrintUpperString;d1(Hello);}
}输出
hello
HELLO7. 泛型接口
interface IMyIfcT
{T ReturnIt(T invalue);
}class Simple: IMyIfcint, IMyIfcstring
{// 因为 Simple 类实现了两个接口所以它必须实现两个接口的相同方法。public int ReturnIt(int invalue){return invalue;}public string ReturnIt(string invalue){return invalue;}
}class Program
{static void Main(){IMyIfcint intIfc new Simple();IMyIfcstring stringIfc new Simple();Console.WriteLine(intIfc.ReturnIt(10));Console.WriteLine(stringIfc.ReturnIt(Hello));}
}本章小结主要通过例子讲解了 C# 语言当中泛型{类、接口、结构、委托、方法}的用法。
各位道友码字不易记得一键三连啊。