C#泛型语法详解

一、为什么要有泛型?

我们在写一些方法时可能会方法名相同,参数类型不同的方法,这种叫做重载。如果只是因为参数类型不同里面做的业务逻辑都是相同的,那可能就是复制粘贴方法,改变参数类型,例如一些排序算法,int、float、double等类型的排序,参数数组存的数据类型不一样,还有像根据索引找到List集合中的对象。可能这个对象是Person、Dog等对象,这样方法改变的只是参数类型,那就是能不能写一个方法,传递不同的参数类型呢?于是乎有了泛型。

二、什么是泛型?

泛型通过参数化类型来实现在同一份代码上操作多种数据类型。例如使用泛型的类型参数T,定义一个类Stack<T>,可以用Stack<int>、Stack<string>或Stack<Person>实例化它,从而使类Stack可以处理int、string、Person类型数据。这样可以避免运行时类型转换或封箱操作的代价和风险,类似C++的模板。泛型提醒的是将具体的东西模糊化,这与后面的反射正好相反。

三、泛型demo

1.泛型类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Generic
{
    public class Stack<T>
    {
        private T[] s;

        int pos;

        public Stack(int size)
        {
            s = new T[size];
            pos = 0;
        }

        public void Push(T val)
        {
            s[pos] = val;
            pos++;
        }

        public T Pop()
        {
            pos--;
            return s[pos];
        }

        public void display()
        {
            Console.WriteLine("Stack Push:");
            foreach (T i in s)
            {
                Console.WriteLine(i);
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Generic
{
    class Program
    {
        static void Main(string[] args)
        {
            Stack<int> s1 = new Stack<int>(2);
            s1.Push(1);
            s1.Push(2);
            s1.display();

            Console.WriteLine("Stack Pop:");
            Console.WriteLine(s1.Pop());
            Console.WriteLine(s1.Pop());

            Stack<string> s2 = new Stack<string>(2);
            s2.Push(@"One");
            s2.Push(@"Two");
            s2.display();

            Console.WriteLine("Stack Pop:");
            Console.WriteLine(s2.Pop());
            Console.WriteLine(s2.Pop());

            Console.ReadLine();
        }
    }
}

上面定义了一个泛型类,主要是维护一个栈,栈里存放T类型的数据,在demo中可以定义int、string类型的栈,这样就很方便,使用一套代码可以维护多种数据类型。如果没有这个可能还要维护double、float等代码。

2.泛型方法

上面是泛型类,主要是在类层面进行参数化,我们还可以在更小的层面,在函数上进行泛型化。

我们可以在上面Mina类中定义一个静态的泛型方法,用来获取找数值在数组中的位置。

public static int Find<T>(T[] valus, T val)
{
    for (int i = 0; i < valus.Length; i++)
    {
        if (valus[i].Equals(val))
        {
            return i;
        }
    }
    return -1;
}

我们可以用上面的方法来查找int数组、float数组

int val = 4;
int pos = Find<int>(new int[] {1,2,3,4,5 },val);
Console.WriteLine(string.Format("int Pos:{0}",pos));

float val1 = 4;
pos = Find<float>(new float[] { 1, 2, 3, 4, 5 }, val1);
Console.WriteLine(string.Format("float Pos:{0}", pos));
Console.ReadLine();

下面是两个demo的输出

四、约束

约束是指对泛型类型参数施加限制,用于限制可以传递到该类型参数的类型种类。如果使用某个约束不允许的类型来实例化,则会产生编译时错误。约束使用where关键字指定。

约束有4种类型:

  • 1.基类约束

指定编译器泛型类型参数必须派生自特定基类

修饰符 class 类名<类型参数列表> where 类型参数:基类名

{ 类体}

  • 2.接口约束

指定编译器泛型类型参数必须派生自特定接口

修饰符 class 类名<类型参数列表> where 类型参数:接口名

{ 类体}

  • 3.默认构造函数约束

指示编译器泛型类型参数公开了默认的公共构造函数(不带任何参数的公共构造函数)

修饰符 class 类名<类型参数列表> where 类型参数:new ()

{ 类体}

  • 4.引用/值类型约束

指示编译器泛型类型参数必须是引用类型或值类型

修饰符 class 类名<类型参数列表> where 类型参数:struct(或class)

{ 类体}

可以对同一类型参数使用多个约束,并且约束自身可以也可以是泛型类型,多个约束之间用逗号隔开。

五、泛型委托

泛型委托主要是想讲一下Action<T>和Func<TResult>两个委托,因为这两个在Linq中是经常见到的。

  • Action<T>只能委托必须是无返回值的方法
  • Fun<TResult>只是委托必须有返回值的方法

不管是不是泛型委托,只要是委托委托那能用Lamdba表达式,因为不管Lamdba表达式还是匿名函数其实都是将函数变量化。

下面简单的来做的demo说下两个的用法,这个会了基本linq会了一半了。

Action<string> action = s => {
	Console.WriteLine(s);
};
action("cuiyanwei");

Func<int, int, int> func = (int a, int b)=>{
	return a + b;
};
int result=func(1, 2);
Console.WriteLine("sum:{0}",result);

Console.ReadLine();

上面其实都是将函数做为变量,这也是委托的思想。action是实例化了一个只有一个字符串参数没有返回值得函数变量。func是实例化了一个有两个int类型的参数返回值为int的函数变量。下面来看下输出结果:

我们可以看到通过Lamdba表达式和泛型的结合,算是又方便了开发者们,更加方便实用。

到此这篇关于C#泛型语法的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • C#之泛型详解

    目录 一.泛型的特性 1.性能 2.类型安全 3.二进制代码的重用 4.代码的扩展 5.命名约定 二.使用类型 1.先创建一个非泛型的简化链表类. 2.下面编写一个泛型版本 三.泛型类的功能 1.默认值 2.约束 3.继承 4.静态成员 四.泛型接口 五.泛型结构 六.泛型方法 1.带约束的泛型方法 2.带委托的泛型方法 3.泛型方法规范 泛型不仅是C#的一部分,而且与程序集中的IL代码紧密地集成.有了泛型,就可以创建独立于被包含类型的类和方法.这样就可以不必给不同的类型编写功能相同的许多方法或

  • 详解c# 泛型类的功能

    在泛型类中,由于不知道泛型参数T是什么类型,可能是引用类型,也可能是值类型,因此不能将null等赋予泛型类型.如何对泛型对象赋初值.如何保证泛型的正确性等,以使用泛型文档管理器为例: 文档管理器用于从队列中读写文档.首先创建一个泛型管理器AddDocument()方法添加一个文档到队列中,IsDocumentAvailabe只读属性指示队列中是否还有文档. public class DocumentManager<T> { private readonly Queue<T> doc

  • C#泛型详解及关键字作用

    这篇文章主要来讲讲c#中的泛型,因为泛型在c#中有很重要的位置,对于写出高可读性,高性能的代码有着关键的作用. 一.什么是泛型? 泛型是 2.0 版 C# 语言和公共语言运行库 (CLR) 中的一个非常重要的新功能. 我们在编程程序时,经常会遇到功能非常相似的模块,只是它们处理的数据不一样.但我们没有办法,只能分别写多个方法来处理不同的数据类型.这个时候,那么问题来了,有没有一种办法,用同一个方法来处理传入不同种类型参数的办法呢?泛型的出现就是专门来解决这个问题的,可以看出,微软还是很贴心的.

  • 详细介绍C# 泛型

    在C#开发中,必不可少的要用到泛型.泛型是.NET2.0版本就有的,它广泛应用于C#框架中容器的使用中.下面我们来详细介绍一下. 一.泛型的主要优势 1.性能更高. 2.类型更安全. 3.代码更多的重用和扩展性. 二.泛型的基本使用 泛型的一个主要优点是性能,我们来看下面的例子: static void Main(string[] args) { //不是泛型的集合类 ArrayList list = new ArrayList(); //添加一个值类型 装箱操作 list.Add(12); /

  • C#泛型类型知识讲解

    概述 泛型类和泛型方法兼具可重用性.类型安全性和效率,这是非泛型类和非泛型方法无法实现的 泛型通常与集合以及作用于集合的方法一起使用 泛型所属命名空间:System.Collections.Generic 可以创建自定义泛型接口.泛型类.泛型方法.泛型事件和泛型委托,以提供自己的通用解决方案,设计类型安全的高效模式 泛型允许编写一个可以与任何数据类型一起工作的类或方法 示例 using System; using System.Collections.Generic; namespace Gen

  • C#泛型的使用及示例详解

    目录 一.什么是泛型 二.为什么使用泛型 三.泛型类型参数 四.泛型类 五.泛型约束 六.泛型的协变和逆变 七.泛型缓存 这篇文章主要讲解C#中的泛型,泛型在C#中有很重要的地位,尤其是在搭建项目框架的时候. 一.什么是泛型 泛型是C#2.0推出的新语法,不是语法糖,而是2.0由框架升级提供的功能. 我们在编程程序时,经常会遇到功能非常相似的模块,只是它们处理的数据不一样.但我们没有办法,只能分别写多个方法来处理不同的数据类型.这个时候,那么问题来了,有没有一种办法,用同一个方法来处理传入不同种

  • C#泛型详解

    这篇文章主要讲解C#中的泛型,泛型在C#中有很重要的地位,尤其是在搭建项目框架的时候. 一.什么是泛型 泛型是C#2.0推出的新语法,不是语法糖,而是2.0由框架升级提供的功能. 我们在编程程序时,经常会遇到功能非常相似的模块,只是它们处理的数据不一样.但我们没有办法,只能分别写多个方法来处理不同的数据类型.这个时候,那么问题来了,有没有一种办法,用同一个方法来处理传入不同种类型参数的办法呢?泛型的出现就是专门来解决这个问题的. 二.为什么使用泛型 先来看下面一个例子: using System

  • C#语法之泛型的多种应用

    本篇文章主要介绍泛型的应用. 泛型是.NET  work 2.0 版类库就已经提供的语法,主要用于提高代码的可重用性.类型安全性和效率. 泛型的定义 下面定义了一个普通类和一个泛型类,我们可以明确看到泛型类和普通类最大的区别就是多了一个<T>. 所以,这个<T>就标记了,这个类是泛型类.其中这个T,也可以写成A,B,C,D或其他字符. public class Generic { public String Name; } public class Generic<T>

  • C#泛型语法详解

    一.为什么要有泛型? 我们在写一些方法时可能会方法名相同,参数类型不同的方法,这种叫做重载.如果只是因为参数类型不同里面做的业务逻辑都是相同的,那可能就是复制粘贴方法,改变参数类型,例如一些排序算法,int.float.double等类型的排序,参数数组存的数据类型不一样,还有像根据索引找到List集合中的对象.可能这个对象是Person.Dog等对象,这样方法改变的只是参数类型,那就是能不能写一个方法,传递不同的参数类型呢?于是乎有了泛型. 二.什么是泛型? 泛型通过参数化类型来实现在同一份代

  • Android Kotlin开发实例(Hello World!)及语法详解

    Android Kotlin开发实例及语法详解 前言 Kotlin是一种在 Java虚拟机上执行的静态型别编程语言,它主要是由俄罗斯圣彼得堡的JetBrains开发团队所发展出来的编程语言.该语言有几个优势 1. 简洁 它大大减少你需要写的样板代码的数量. 2. 安全 避免空指针异常等整个类的错误. 3. 通用 构建服务器端程序.Android 应用程序或者在浏览器中运行的前端程序. 4. 互操作性 通过 100% Java 互操作性,利用 JVM 既有框架和库. 配置 在我们的AndroidS

  • java伪泛型知识点详解

    说明 1.Java中的泛型是伪泛型.这种泛型实现方法称为类型擦除 ,基于这种方法实现的泛型称为伪泛型. 2.由于Java的泛型只在编译阶段发挥作用,因此在写代码时,起到了检查的作用,当代码运行时,它的内部并没有泛型. 实例 List<String> l1 = new ArrayList<String>(); List<Integer> l2 = new ArrayList<Integer>(); System.out.println(l1.getClass(

  • DOS批处理中%~dp0等扩充变量语法详解

    有时候我们看到别人使用%~dp0 ~是扩展的意思,相当于把一个相对路径转换绝对路径 %0代指批处理文件自身 %1表示批处理文件命令行接收到的第一个参数,%2表示第二个,以此类推 %~d0 是指批处理所在的盘符,其中d代表drive %~p0 是指批处理所在的目录,其中p代表path %~dp0 是批处理所在的盘符加路径 cd %~dp0 就是进入批处理所在目录了 详细解释还可参考命令 call /? DOS批处理中%~dp0表示什么意思 (注: %0 就是该 batch 文件的文件名) 这句的意

  • 基于JS脚本语言的基础语法详解

    JS脚本语言的基础语法:输出语法  alert("警告!");  confirm("确定吗?");   prompt("请输入密码");为弱类型语言: 开始时要嵌入JS代码:<script type="text/javascript"></script>: 关于写程序是需注意的基本语法: 1.所有的字符全都是英文半角的: 2.大部分情况下每条语句结束后要加分号: 3.每一块代码结束后加换行:4.程序前呼

  • java 泛型的详解及实例

    java 泛型的详解及实例 Java在1.5版本中增加了泛型,在没有泛型之前,从集合中读取每一个对象都需要进行强转,如果一不小心插入了类型错误的对象,在运行时就会报错,给日常开发带来了很多不必要的麻烦,比如以下代码: public class TestGeneric { public static void main(String[] args) { List list = new ArrayList(); list.add(" name:"); list.add(" zer

  • kotlin 官方学习教程之基础语法详解

    kotlin 官方学习教程之基础语法详解 Google 在今天的举行了 I/O 大会,大会主要主要展示内有容 Android O(Android 8.0)系统.Google Assistant 语音助手.Google 智能音箱.人工智能.机器学习.虚拟现实等.作为一个 Android 开发者,我关心的当然是 Android O(Android 8.0)系统了,那么关于 Android O 系统的一个重要消息是全面支持 Kotlin 编程语言,使得 Kotlin 成为了 Android 开发的官方

  • 对Golang import 导入包语法详解

    package 的导入语法 写 Go 代码的时经常用到 import 这个命令用来导入包,参考如下: import( "fmt" ) 然后在代码里面可以通过如下的方式调用: fmt.Println( "我爱北京天安门" ) fmt 是 Go 的标准库,它其实是去 GOROOT 下去加载该模块,当然 Go 的 import 还支持如下两种方式来加载自己写的模块: 相对路径 import "./model" // 当前文件同一目录的 model 目录

  • laravel高级的Join语法详解以及使用Join多个条件

    在laravel中我们常常会使用join,leftjion和rightjoin进行连表查询,非常的方便,但是我今天遇到一个问题,就是链表查询需要on多个条件,即我要订单的id和发货人都一样,默认的join只支持单个查询,所以我下面总结两种方法: 一.使用原是表达式(不推荐) 原生SQL中我们可以通过如下方法进行 select * from `orders` left join `users` on `orders`.`usename`=`users`.`usename` and `orders`

  • 对Python 3.5拼接列表的新语法详解

    在Python 3.5之前的版本,拼接列表可以有这两种方法: 1.列表相加 list1 = [1,2,3] list2 = [4,5,6] result = list1 + list2 结果为一个新的列表 2.在原来列表上扩展 list1 = [1,2,3] list2 = [4,5,6] list1.extend(list2) list1扩展后,结果为[1,2,3,4,5,6] 3.新语法 如果列表是由range()生成: list1 = [1,2,3] list2 = range(4,6)

随机推荐