当前位置: 首页 > 编程日记 > 正文

技术图文:C#语言中的泛型 II

C#语言中的泛型 II

知识结构:

图1 知识结构


6. 泛型接口

泛型类与泛型接口结合使用是很好的编程习惯,比如用IComparable<T>而非IComparable,以避免值类型上的装箱和拆箱操作。若将接口指定为类型参数的约束(接口约束),则要使用实现此接口的类型。在设计泛型接口时,我们需要注意以下几点:

(1)一个接口可以定义多个类型参数,如下所示:

public interface IDictionary<TK, TV>
{//...
}

(2)可以用多个接口为类型参数指定接口约束,如下所示:

public class Stack<T> where T : IComparable<T>, IEnumerable<T>
{//...
}

(3)具体类可以实现封闭结构类型的接口,如下所示:

public interface IBaseInterface<T>
{//...
}public class SampleClass : IBaseInterface<string>
{//...
}

(4)泛型类可以实现泛型接口但要注意类型参数,如下所示:

public interface IBaseInterface1<T>
{//...
}public interface IBaseInterface2<T, TU>
{//...
}public class SampleClass1<T> : IBaseInterface1<T>
{// 泛型类实现开放构造类型的接口
}public class SampleClass2<T> : IBaseInterface2<T, string>
{// 除了与接口共用的类型参数外,必须为所有的其它类型参数指定类型
}

(5)适用于类的继承规则同样适用于接口,如下所示:

public interface IMonth<T>
{//...
}public interface IMonth<T,U>
{//...
}public interface IJanuary : IMonth<int>
{//...
}public interface IFebruary<T> : IMonth<T>
{//...
}public interface IMarch<T> : IMonth<T, int>
{//...
}//public interface IApril<T> : IMonth<T, U>
//{
//    // Error
//}

7. 泛型方法

(1)泛型方法的定义

声明了类型参数的方法,称为泛型方法。如下所示:

class Program
{private static void Swap<T>(ref T lhs, ref T rhs){T temp = lhs;lhs = rhs;rhs = temp;}public static void TestSwap(){int a = 1, b = 2;Swap<int>(ref a, ref b); //int作为类型参数,调用方法。//也可以忽略类型参数<int>,与上面的语句等价,编译器会自动推断它。Swap(ref a, ref b);Console.WriteLine(a + " " + b);}static void Main(string[] args){TestSwap();// 1 2}
}

静态方法和实例方法有着同样的类型推断规则。

类型推断对没有参数的方法是无效的,因为编译器无法单独根据约束或返回值来进行推断。

类型推断发生在编译器解析重载方法标志之前,对所有同名的泛型方法应用类型推断逻辑。在决定重载的阶段,编译器只包含哪些类型推断成功的泛型类。

(2)泛型方法的参数类型约束

private void SwapIfGreater<T>(ref T lhs, ref T rhs)where T : IComparable<T>
{//只能与实现IComparable<T>的类型参数一起使用。if (lhs.CompareTo(rhs) > 0){T temp = lhs;lhs = rhs;rhs = temp;}
}

(3)泛型方法的重载

泛型方法可以通过多个类型参数来重载。

例如,下面的这些方法可以放在同一个类中:

private void DoWork()
{//...
}
private void DoWork<T>()
{//...
}
private void DoWork<T, TU>()
{T a = default(T);TU b = default(TU);//...
}

(4)泛型类中的泛型方法

public class SampleClass<T>
{private void Swap(ref T lhs, ref T rhs){// 非泛型方法能访问所在类中的类型参数}
}public class GenericList<T>
{private void SampleMethod<T>(){// 警告 CS0693// 类型参数“T”与外部类型“GenericList<T>”中的类型参数同名}
} 
public class GenericList2<T>
{private void SampleMethod<TU>(){//No Warning}
}

若定义的泛型方法和其所在的类具有相同的类型参数,编译器就会产生警告CS0693,因为在方法范围内为内部T提供的参数隐藏了为外部T提供的参数。如果需要使用其它类型参数(而不是实例化类时提供的类型参数)来灵活地调用泛型类方法,要为方法的类型参数提供另一个标识符。

泛型方法实例:

public interface IAccount
{string Name { get; }decimal Balance { get; }
}public class Account : IAccount
{public string Name { get; }public decimal Balance { get; }public Account(string name, decimal balance){Balance = balance;Name = name;}
}public class Algorithm
{public static decimal Total<T>(IEnumerable<T> e)where T : IAccount{decimal total = 0;foreach (T a in e){total += a.Balance;}return total;}
}class Program
{static void Main(string[] args){List<Account> accounts = new List<Account>();accounts.Add(new Account("Tom", 999.99m));accounts.Add(new Account("Jonh", 1241.33m));accounts.Add(new Account("Patrick", 1551.2m));accounts.Add(new Account("Candy", 2647m));decimal total = Algorithm.Total(accounts);Console.WriteLine("total:{0:C}", total);// total:¥6,439.52}
}

8. 泛型委托

(1)泛型委托的定义

public delegate void Del<T>(T item);class Program
{public static void Notify(int i){//...}static void Main(string[] args){Del<int> m1 = new Del<int>(Notify);// ...}
}

使用时与实例化泛型类或调用泛型方法一样,需要指定类型参数。

C# 2.0之后有个新特性为 方法组转换(Method Group Conversion,从方法组到一个兼容委托类型的隐式转换,“方法组”可以看作一个“方法名”),普通委托和泛型委托都可以使用这一特性进行语法简化,如下所示:

public delegate void Del<T>(T item);class Program
{public static void Notify(int i){//...}static void Main(string[] args){Del<int> m1 = Notify;// ...}
}

(2)在泛型类中定义的委托,可以与类的方法一样使用泛型类的类型参数。

public class Stack<T>
{private T[] _items;private int _index;public delegate void StackDelegate(T[] items);
}class Program
{private static void DoWork(float[] items){//...}static void Main(string[] args){Stack<float> s = new Stack<float>();Stack<float>.StackDelegate d = DoWork;        // ...}
}

(3)泛型委托在定义事件时sender可以定义为强类型,不用再与Object类型相互转换。

public delegate void StackEventHandler<T, TU>(T sender, TU eventArgs);public class Stack<T>
{public class StackEventArgs : EventArgs{public T X { get; set; }public T Y { get; set; }}public event StackEventHandler<Stack<T>, StackEventArgs> StackEvent;public virtual void OnStack(StackEventArgs a){StackEvent?.Invoke(this, a);}
}public class SampleClass
{public void HandleStackChange<T>(Stack<T> stack, Stack<T>.StackEventArgs args){//...Console.WriteLine("Test Delegate<T>:{0},{1}", args.X, args.Y);}
}class Program
{static void Main(string[] args){Stack<string> s = new Stack<string>();s.StackEvent += new StackEventHandler<Stack<string>, Stack<string>.StackEventArgs>(new SampleClass().HandleStackChange);//s.StackEvent += new SampleClass().HandleStackChange;//与上一行语句等价Stack<string>.StackEventArgs args1 = new Stack<string>.StackEventArgs();args1.X = "Hello";args1.Y = "World";s.OnStack(args1);//Test Delegate<T>:Hello,World}
}

9. default关键字

在泛型类和泛型方法中会出现一个问题:如果把缺省值赋给参数化类型,此时无法预先知道以下两点:

  • T将是值类型还是引用类型。
  • 如果T是值类型,那么T将是数值还是结构。

对于一个参数化类型T的变量t,仅当T是引用类型时,t = null语句才是合法的;t = 0只对数值的有效,而对结构体则不行。

这个问题的解决办法是使用default关键词,它对引用类型返回null,对值类型的数值型返回零。而对于结构,它将返回结构每个成员,并根据成员是值类型还是引用类型,返回零或null

public class GenericList<T>
{private class Node{//...public Node Next;public T Data;}//...private Node head;private Node current;public T GetNext(){T temp = default(T);if (current != null){temp = current.Data;current = current.Next;}return temp;}
}

后台回复「搜搜搜」,随机获取电子资源!
欢迎关注,请扫描二维码:



相关文章:

linux档案权限

Linux 下的档案当你对一个档案具有w权限时&#xff0c;你可以具有写入/编辑/新增/修改档案的内容的权限&#xff0c; 但并丌具备有删除该档案本身的权限&#xff01;对二档案的rwx来说&#xff0c; 主要都是针对『档案的内容』而觊&#xff0c;不档案档名的存在不否没有关系喔&…

新手UI设计师需要掌握的知识和技能

UI设计岗位在近几年的需求是越来越高的&#xff0c;很多零基础学员都开始学习UI设计技术&#xff0c;那么想要成为一名合格的UI设计师&#xff0c;新手UI设计师需要掌握的知识和技能是比较要会的&#xff0c;来看看下面的详细介绍。 新手UI设计师需要掌握的知识和技能&#xff…

数据结构与算法:04 C#面向对象设计 II

04 C#面向对象设计 II 知识结构&#xff1a; 5、属性 例1&#xff1a;属性概念的引入&#xff08;问题&#xff09; public class Animal {public int Age;public double Weight;public bool Sex;public Animal(int age, double weight, bool sex){Age age;Weight weight;S…

SharePoint迁移和升级方案

这是之前针对SharePoint迁移和升级写的方案&#xff0c;去掉了敏感的部分&#xff0c;共大家交流吧。SharePointMigrationSolution转载于:https://www.cnblogs.com/zhaojunqi/archive/2012/04/12/2444803.html

零基础如何掌握web前端开发技能

很多零基础学员想要进入到互联网行业都会选择web前端做首选技术语言来学习&#xff0c;但是学习web前端不是那么容易的&#xff0c;想要成为一名合格的web前端工程师&#xff0c;所要掌握的技能一定要会&#xff0c;下面小编就为大家详细的介绍一下零基础如何掌握web前端开发技…

数据结构与算法:05 Leetcode同步练习(一)

Leetcode同步练习&#xff08;一&#xff09; 题目01&#xff1a;两数之和 题号&#xff1a;1难度&#xff1a;简单https://leetcode-cn.com/problems/two-sum/ 给定一个整数数组 nums 和一个目标值 target&#xff0c;请你在该数组中找出和为目标值的那 两个整数&#xff0c;…

用Asp.net实现简单的文字水印

经常看见MOP上有人贴那种动态的图片&#xff0c;就是把一个字符串作为参数传给一个动态网页&#xff0c;就会生成一个带有这个字符串的图片&#xff0c;这个叫做文字水印。像什么原来的熊猫系列&#xff0c;还有后来的大树和金条&#xff0c;都挺有意思。这东西看着挺好玩的&am…

yum国内镜像

Centos-7修改yum源为国内的yum源 国外地址yum源下载慢,下到一半就断了,就这个原因就修改它为国内yum源地址 国内也就是ali 与 网易 以centos7为例 ,以 修改为阿里的yum源 先确定有wget 备份本地yum源 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo_…

HTML的标签分为哪几类?各标签语法格式是怎样的?

HTML的标签分为哪几类?各标签语法格式是怎样的?相信大家在学习HTML课程的时候&#xff0c;有讲到这方面的知识&#xff0c;根据标签的组成特点&#xff0c;通常将HTML标签分为两大类&#xff0c;分别是“双标签”、“单标签”&#xff0c;对它们的具体介绍如下。 1.双标签 双…

数据结构与算法:06 线性表

06 线性表 知识结构&#xff1a; 1. 线性表的定义与操作 1.1 线性表的定义 线性表&#xff08;Linear List&#xff09;是由n(n≥0)n (n≥0)n(n≥0)个相同类型的数据元素a0,a1,⋯,an−1a_0,a_1,⋯,a_{n-1}a0​,a1​,⋯,an−1​组成的序列。即表中除首尾元素外&#xff0c;其…

MySQL提权简单方法

前不久网上公开了一个MySQL Func的漏洞,讲的是使用MySQL创建一个自定义的函数,然后通过这个函数来攻击服务器。最早看到相关的报道是在o-otik上,但是公布的是针对 Unix系统的Exploit,并且成功率也不是很高.而近期,国内有高手放出针对Win系统的相关文章,于是我马上找来与朋友一同…

转载LINQ优点 自己学习用的

这几天在读一本LINQ方面的书《Essential LINQ》,在这里和大家分享下。 由于对LINQ的深入总结需要大量的篇幅&#xff0c;因此在这里分成几个部分来讲。 &#xff08;*我看《Essential LINQ》是英文版的&#xff0c;有些名词不能翻译成正统的中文解释请给予谅解&#xff09; LIN…

什么是Python?好学吗?

互联网IT行业是很多人都比较关注的行业&#xff0c;大部分都想学习IT技术进入到这个行业&#xff0c;Python编程语言在近几年是多数人的选择&#xff0c;那么什么是Python?好学吗?具体来看看下面的详细介绍吧。 一、什么是python 网络上对python的解释是一门解释型、面向对象…

数据结构与算法:07 Leetcode同步练习(二)

目录 题目01&#xff1a;回文数题目02&#xff1a;x 的平方根题目03&#xff1a;爬楼梯题目04&#xff1a;买卖股票的最佳时机题目05&#xff1a;买卖股票的最佳时机 II题目06&#xff1a;跳跃游戏题目07&#xff1a;三数之和题目08&#xff1a;最接近的三数之和题目09&#x…

(五)Docker镜像和容器

之所以在之前没有讲什么是镜像和容器是因为如果你没有一个最初的认识&#xff0c;那么你就很难理解镜像和容器以及它们的区别。我相信在前面一章中的讲述中&#xff0c;你应该稍有体会容器是基于镜像构建的&#xff0c;同时构建了容器之后如果不删除就会一直存在&#xff0c;而…

翻译-高质量JavaScript代码书写基本要点(转载)

by zhangxinxu from http://www.zhangxinxu.com本文地址&#xff1a;http://www.zhangxinxu.com/wordpress/?p1173 原文作者&#xff1a;Stoyan Stefanov原文链接&#xff1a;The Essentials of Writing High Quality JavaScript 翻译编辑&#xff1a;张鑫旭//zxx: 俗不可耐的…

学习ui设计的流程是什么

UI设计在如今的市场行情中是很多企业都必不可少的一个技术岗位&#xff0c;UI设计是比较注重自身产品的用户体验的&#xff0c;想要学习UI设计&#xff0c;一定要做足功课&#xff0c;下面小编就为大家详细的介绍一下学习ui设计的流程是什么? 学习ui设计的流程是什么?总体进程…

数据结构与算法:08 Leetcode同步练习(三)

目录 题目01&#xff1a;合并两个有序链表题目02&#xff1a;删除排序链表中的重复元素题目03&#xff1a;环形链表题目04&#xff1a;反转链表题目05&#xff1a;删除链表中的节点题目06&#xff1a;两数相加题目07&#xff1a;删除链表的倒数第N个节点题目08&#xff1a;两两…

Linux之进程管理

程序是保存在外部存储设备&#xff08;如硬盘&#xff09;中的可执行机器代码和数据的集合。而进程是在CPU及内存中处于动态执行状态的计算机程序。每个程序启动后会产生一个或多个进程&#xff0c;如httpd程序&#xff0c;当有大量用户访问Web页面时&#xff0c;httpd程序会产…

win8 metro 拖拽重排grid

0.1 http://1.metrowin8.sinaapp.com/Code/index.html 拖拽重排实现思路 &#xff1a; 1.初始化拖拽对象时&#xff0c;上传拖拽对象中心点信息(包括id,className) 2.鼠标按下时&#xff0c;制造一个假的拖拽对象 3.鼠标放开时&#xff0c;计算鼠标与拖拽对象中心点的距离&…

什么是AngularJS?它有哪些特性?

AngulaJS是款非常优秀的JasSetpsn结构化框架,可以用来构建单页面应用程序&#xff0c;2009年,AngularJS由Misko Hevery等人创建&#xff0c;后来被Google收购&#xff0c;该技术已经被用于Coogle旗下的多款产品开发当中。开发人员不仅可以使用和扩展HTML语言的特性。而且可以更…

ELK安装文档及相关优化

前言&#xff1a;随着硬件成本的不断低廉&#xff0c;我们可以存储更多数据内容&#xff0c;也会对各数据加以利用&#xff0c;其中一项很重要的数据内容便是日志文件&#xff0c;无论是访问日志还是系统日志或是应用日志&#xff0c;都显得十分重要&#xff0c;而怎么加以利用…

数据结构与算法:09 栈与递归

09 栈与递归 知识结构&#xff1a; 栈是我们经常使用的一种数据结构&#xff0c;比如&#xff0c;手枪发射子弹的顺序与子弹压入弹夹的顺序是相反&#xff0c;即后压入弹夹的子弹先发射出来。又比如&#xff0c;我们使用的Word、Excel、Photoshop等软件系统中的撤销操作&#…

Javascript匿名函数

定义 匿名函数的定义非常简单&#xff1a;就是没有名字的函数。但是其用途非常的大 典型的函数定义方式 在看匿名函数之前我们先看下在Javascript中定义一个函数比较典型的几种方式 函数声明 function functionName(args) { //函数体 } 函数表达式 var functionName functi…

零基础学Java大数据难不难

java大数据如今在企业中用到的次数是非常多的&#xff0c;很多人都比较看好java技术&#xff0c;那么零基础学Java大数据难不难?想要学习java技术说难不难&#xff0c;说简单也不是很简单&#xff0c;来看看下面的详细介绍就知道了。 零基础学Java大数据难不难?因人而异&…

技术图文:01 面向对象设计原则

01 面向对象设计原则 知识结构&#xff1a; 一碟开胃的小菜 小菜今年计算机专业大四了&#xff0c;学了不少软件开发方面的东西&#xff0c;也学着编了些小程序&#xff0c;踌躇满志&#xff0c;一心要找一个好单位。当投递了无数简历后&#xff0c;终于收到了一个单位的面试…

关于GridView手动绑定的一段代码,一切尽在不言中

为GridView绑定主键的方法&#xff0c;在前台的DataGrid标签中加 DataKeyNames"ID" 后台获取ID&#xff1a; int idint.parse(this.GridView.DataKeys[e.RowIndex].Value.Tostring()); 如果DataKeyNames绑定了多个列取法&#xff1a;int idint.parse(this.G…

linux 服务器FTP服务安装教程

1.更新yum源 首先需要更新系统的yum源&#xff0c;便捷工具下载地址&#xff1a;http://help.aliyun.com/manual?spm0.0.0.0.zJ3dBU&helpId1692 2.安装vsftp 使用yum命令安装vsftp #yum install vsftpd -y 3.添加ftp帐号和目录 先检查一下nologin的位置&#xff0c;通常在…

CSS3颜色不透明度如何设置

web前端技术包含HTML和CSS样式&#xff0c;两者是相辅相成的&#xff0c;学习CSS样式不必可少&#xff0c;那么在学习CSS样式中&#xff0c;CSS3颜色不透明度如何设置?在CSS3之前&#xff0c;我们设置颜色的方式包含十六进制颜色(如#F00)、rgb模式颜色、或指定颜色的英文名称(…

技术图文:02 创建型设计模式(上)

创建型设计模式&#xff08;上&#xff09; 知识结构&#xff1a; 图1 知识结构 简单工厂模式 Sunny 软件公司欲基于 C# 语言开发一套图表库&#xff0c;该图表库可以为应用系统提供各种不同外观的图表&#xff0c;如&#xff1a; 柱状图&#xff08;histogram&#xff09;饼…