一起谈.NET技术,浅谈.Net中容易混淆的委托和接口

简介:   本文适合对委托和接口概念非常了解的朋友,并且欢迎各位朋友与Snake一起探讨有关这方面的知识.本文不适合对委托和接口概念或用途了解一知半解(模糊)的朋友,这篇文章可能会对您产生误导,请千万别看.  在文章正式开始之前我需要将MSDN上对委托和接口的内容放上来,作为文章之基.  委托:  委托是一种定义方法签名的类型。

  本文适合对委托和接口概念非常了解的朋友,并且欢迎各位朋友与Snake一起探讨有关这方面的知识.本文不适合对委托和接口概念或用途了解一知半解(模糊)的朋友,这篇文章可能会对您产生误导,请千万别看.

  在文章正式开始之前我需要将MSDN上对委托和接口的内容放上来,作为文章之基.

  委托:

  委托是一种定义方法签名的类型。当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联。您可以通过委托实例调用方法。

  委托用于将方法作为参数传递给其他方法。事件处理程序就是通过委托调用的方法。您可以创建一个自定义方法,当发生特定事件时某个类(例如 Windows 控件)就可以调用您的方法.

  委托具有以下特点:

  委托类似于 C++函数指针,但它们是类型安全的。

  委托允许将方法作为参数进行传递。

  委托可用于定义回调方法。

  委托可以链接在一起;例如,可以对一个事件调用多个方法。

  方法不必与委托签名完全匹配。有关更多信息,请参见在委托中使用变体(C#和 Visual Basic)。

  C# 2.0 版引入了匿名方法的概念,此类方法允许将代码块作为参数传递,以代替单独定义的方法。C# 3.0 引入了 Lambda 表达式,利用它们可以更简练地编写内联代码块。匿名方法和 Lambda 表达式(在某些上下文中)都可编译为委托类型。这些功能统称为匿名函数。有关 Lambda 表达式的更多信息,请参见Anonymous Functions (C# Programming Guide)。

  接口:

  接口描述的是可属于任何类或结构的一组相关功能。接口可由方法、属性、事件、索引器或这四种成员类型的任意组合构成。接口不能包含字段。接口成员一定是公共的。

  当类或结构继承接口时,意味着该类或结构为该接口定义的所有成员提供实现。接口本身不提供类或结构能够以继承基类功能的方式继承的任何功能。但是,如果基类实现接口,派生类将继承该实现。

  类和结构可以按照类继承基类或结构的类似方式继承接口,但有两个例外:

  类或结构可继承多个接口。

  类或结构继承接口时,仅继承方法名称和签名,因为接口本身不包含实现。

  接口具有下列属性:

  接口类似于抽象基类:继承接口的任何非抽象类型都必须实现接口的所有成员。

  不能直接实例化接口。

  接口可以包含事件、索引器、方法和属性。

  接口不包含方法的实现。

  类和结构可从多个接口继承。

  接口自身可从多个接口继承。

  正文开始

  在写这些文字的时候我又将以上的各个概念熟悉了一遍,以防自己把自己忽悠混淆了.所以不适合群众请尽快退散.另外如果您看完上面的定义和特征后就从两者的混淆中走了出来,您也可以尝试继续往下看.

  首先,关于委托的用法,我们可以这样使用:

public int Calculate(Func del){ int a = 1, b = 2; return del(a, b); }

  我们可以通过传不同的Func来改变整个方法的结果.

public int Add(int a, int b)
{ return a + b; } 
public int Sub(int a, int b)
{ return a - b; }
//调用方法如下 
public void TestMethod()
{ int result = Calculate(Add);
//the result is 3 int anotherResult = Calculate(Sub);//the result is -1 }

  首先我在Calculate方法中已经确定了2个数的值,并且包括在该方法当中.在输出结果的时候能明显看出传递的委托不同,其结果也不同.我们使用委托来改变方法的执行内容,我们不但可以改变其方法的内容,也可以在执行该方法的时候顺便做点什么(比如说做个日志记录).

  噢,可能您觉得二者容易混淆的地方在于..我还是举个例子比较好解释.

public interface ICal { int Calculate(int a, int b); }//有多个类实现了ICal接口. 
public class Add : ICal { public int Calculate(int a, int b){ return a + b; }} 
public class Sub : ICal { public int Calculate(int a, int b)
{ return a - b; }}//然后通过调用不同类来获取不同的方法 
public static void Main(){ ICal cal = new Add(); 
//ICal=new Sub(); Console.Write(cal.Calculate(1, 2)); }

  讲解一下,通过上面的例子我们可以知道在创建一个具有计算功能(Calculate)的接口ICal之后,产生了两个具有计算功能的具体类,分别是Add和Sub.为了要获得结果,我们创建了一个需要有计算功能的”坑”,并赋予能与此”坑”相匹配的类Add(或Sub),最后从该坑中调用Calculate的结果就行.

  貌似说的过去?好,那么我至少要让你觉得有个适用范围吧!看下面的例子.

  比如有个Person类的数组arr.这时候我们可以通过委托的方法实现arr的排序.可是系统怎么知道2个Person哪个排在前面,哪个该排在后面?这时候我们就可以传进一个委托来告诉系统Peron类的大小.

arr.Sort(p => { p.ID });

  该lambda表达式意思是丢给该Sort方法一个排序的Key(此key能够进行大小比较),那么Sort就可以根据此key来进行比较.那通过接口呢?首先得创建一个继承自IComparer的类,我就拿本身继承它吧.

  好吧,它本来是很麻烦的:

private int SortDelegate(Person p){ return p.ID; }
public void TestMethod(){ arr.Sort(new Func(SortDelegate)); }

  但是我们要承认C# 3.0带给我们的便利.

  现在,我们要让Person类实现接口的规定.

public int Compare(Person x, Person y){//假设person的ID是int类型 return x.ID -y.ID; }

  那么我们的实现方法就可能是这样:

arr.Sort((new Person() as IComparer) comp);

  首先我们看第一个委托例子:在Calculate时我们的委托被允许使用了该方法内的两个变量a,b从而改变了整个方法的结果.在整个过程中委托时很被动的,因为它不知道自己会在什么时候被触发.上面的例子很简单,使您没有这种感觉,而且前面说过在方法执行的时候当委托被触发我们可以干点别的,比如说做个日志记录什么的,此时接口有能力又不破坏方法本身运行结构,又能做日志记录吗?显然实现了接口的类只能重写一遍该方法.

  路人甲:那我在接口的实现中再调用一下原方法,最后在方法的前面或后面加入日志记录功能不就完了吗?

  Snake:杀鸡焉用宰牛刀?且不说再原方法的可行性,就算可行了,麻烦不说,万一这个方法执行有多个阶段,每个阶段都要日志记录呢?委托能深入方法,并且由方法控制它安放之地,让委托能起到关键作用,此时作为接口大哥的牛刀也剔不干净鸡骨上的肉哟~.

  其次说接口的优点.我们前面可以看到委托能深入方法,也就是说委托的关注群体是方法们,而接口关注的群体则是类们.接口让类必须实现相同签名的方法或属性,以便在程序中通过调用可变的方法.既然是因为类的关系,那么它的方法肯定是不可变的了,每个实现了该接口的类,即便功能差不多也要完完全全写一遍,但是类的地盘大,肚子里的墨水多,虽然在Add类中通过ICal可调用的方法也就一个Calculate(),但是在Calculate始终是Add类的子民,所以该Calculate方法可以调用Add类中所有能调用的资源.而如果是Sub类的话,它的子民Caculate可调用的资源又与Add类不尽相同,毕竟同是Calculate,国籍不同,文化和生活方式也不同嘛.

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
7天前
|
开发框架 .NET 中间件
七天.NET 8操作SQLite入门到实战 - (2)第七天Blazor班级管理页面编写和接口对接
七天.NET 8操作SQLite入门到实战 - (2)第七天Blazor班级管理页面编写和接口对接
|
8天前
|
人工智能 开发框架 量子技术
【专栏】.NET 技术:驱动创新的力量
【4月更文挑战第29天】.NET技术,作为微软的开发框架,以其跨平台、开源和语言多样性驱动软件创新。它在云计算、AI/ML、混合现实等领域发挥关键作用,通过Azure、ML.NET等工具促进新兴技术发展。未来,.NET将涉足量子计算、微服务和无服务器计算,持续拓宽软件开发边界,成为创新的重要推动力。掌握.NET技术,对于开发者而言,意味着握有开启创新的钥匙。
|
8天前
|
开发框架 .NET C#
【专栏】理解.NET 技术,提升开发水平
【4月更文挑战第29天】本文介绍了.NET技术的核心概念和应用,包括其跨平台能力、性能优化、现代编程语言支持及Web开发等特性。文章强调了深入学习.NET技术、关注社区动态、实践经验及学习现代编程理念对提升开发水平的重要性。通过这些,开发者能更好地利用.NET构建高效、可维护的多平台应用。
|
8天前
|
机器学习/深度学习 vr&ar 开发者
【专栏】.NET 技术:引领开发新方向
【4月更文挑战第29天】本文探讨了.NET技术如何引领软件开发新方向,主要体现在三方面:1) 作为跨平台开发的先锋,.NET Core支持多操作系统和移动设备,借助.NET MAUI创建统一UI,适应物联网需求;2) 提升性能和开发者生产力,采用先进技术和优化策略,同时更新C#语言特性,提高代码效率和可维护性;3) 支持现代化应用架构,包括微服务、容器化,集成Kubernetes和ASP.NET Core,保障安全性。此外,.NET还不断探索AI、ML和AR/VR技术,为软件开发带来更多创新可能。
|
8天前
|
开发框架 Cloud Native 开发者
【专栏】剖析.NET 技术的核心竞争力
【4月更文挑战第29天】本文探讨了.NET框架在软件开发中的核心竞争力:1) .NET Core实现跨平台与云原生技术的融合,支持多操作系统和容器化;2) 提升性能和开发者生产力,采用JIT、AOT优化,提供C#新特性和Roslyn编译器平台;3) 支持现代化应用架构,包括微服务和容器化,内置安全机制;4) 丰富的生态系统和社区支持,拥有庞大的开发者社区和微软的持续投入。这些优势使.NET在竞争激烈的市场中保持领先地位。
|
8天前
|
开发框架 .NET 开发者
【专栏】领略.NET 技术的创新力量
【4月更文挑战第29天】.NET技术自ASP.NET起历经创新,现以.NET Core为核心,展现跨平台能力,提升性能与生产力,支持现代化应用架构。.NET Core使开发者能用同一代码库在不同操作系统上构建应用,扩展至移动和物联网领域。性能提升,C#新特性简化编程,Roslyn编译器优化代码。拥抱微服务、容器化,内置安全机制,支持OAuth等标准。未来.NET 6将引入更快性能、Hot Reload等功能,预示着.NET将持续引领软件开发潮流,为开发者创造更多机会。
|
8天前
|
物联网 vr&ar 开发者
【专栏】.NET 技术:为开发注入活力
【4月更文挑战第29天】本文探讨了.NET技术的创新,主要体现在三个方面:1) .NET Core实现跨平台开发革命,支持多种操作系统和硬件,如.NET MAUI用于多平台UI;2) 性能提升与生产力飞跃,C#新特性简化编程,JIT和AOT优化提升性能,Roslyn提供代码分析工具;3) 引领现代化应用架构,支持微服务、容器化,内置安全机制。未来,.NET 7将带来更多新特性和前沿技术整合,如量子计算、AI,持续推动软件开发创新。开发者掌握.NET技术将赢得竞争优势。
|
4月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
46 0
|
12天前
|
开发框架 前端开发 JavaScript
JavaScript云LIS系统源码ASP.NET CORE 3.1 MVC + SQLserver + Redis医院实验室信息系统源码 医院云LIS系统源码
实验室信息系统(Laboratory Information System,缩写LIS)是一类用来处理实验室过程信息的软件,云LIS系统围绕临床,云LIS系统将与云HIS系统建立起高度的业务整合,以体现“以病人为中心”的设计理念,优化就诊流程,方便患者就医。
20 0
|
2月前
|
开发框架 前端开发 .NET
进入ASP .net mvc的世界
进入ASP .net mvc的世界
32 0