C#——委托(1)
什么是委托?
还记得C/C++语言里的函数指针吗?委托就是他的”升级版“。
先看一个简单的小程序:
# include<stdio.h> typedef int(*Calc)(int a, int b);//使用typedef把他定义成一种数据类型 int Add(int a,int b)
{
int result = a + b;
return result;
} int main(void)
{
int x = ;
int y = ;
int z = ; z = Add(x,y);//直接调用
printf("%d+%d=%d\n",x,y,z); Calc cFun = &Add;//间接调用
z = cFun(x, y);
printf("%d+%d=%d\n", x, y, z); return ;
}
直接调用和间接调用他们的运行结果是一样的
变量和函数到底是啥?
变量(代表数据)是以变量名对应的内存地址为起点的一段内存中所存储的值
函数(代表算法)是以函数名对应的内存地址为起点的一段内存中所存储的一组机器语言指令
知道了啥是变量和函数,那就来看看啥是 直接调用和间接调用
直接调用:通过函数名来调用函数,CPU通过函数名直接获得函数所在地址并开始执行,执行完函数后CPU返回调用者那里继续往下执行
间接调用:通过函数指针来调用函数,CPU通过读取函数指针存储的值(函数名所对应的地址)获得函数所在地址并开始执行,最终返回调用者那里继续往下执行
下面我们就看看委托是个什么东西
namespace DelegateExample_Action_
{
class Program
{
static void Main(string[] args)
{
Calculator calculator = new Calculator();
Action action = new Action(calculator.Report);
action.Invoke();//间接引用
/*
还可以这么写
action();
*/
calculator.Report();//直接引用
//运行结果完全一样
}
} class Calculator
{
public void Report()
{
Console.WriteLine("I have three methods.");
}
public int Add(int a, int b)
{
int result = a + b;
return result;
}
public int Sub(int a, int b)
{
int result = a - b;
return result;
}
}
}
IDE提示到,你要往里面放一个返回值为void类型,参数列表为空的一个方法,那么在Calculator类里符合的就是Report方法,所以我们就把Report方法放了进去
运行结果:
第一行是我们直接调用时打印出来的语句,第二行是我们用Action委托打印出来的语句
如果要调用Add或者Sub方法,我们选择使用Func委托:
namespace DelegateExample_Func_
{
class Program
{
static void Main(string[] args)
{
Calculator calculator = new Calculator(); Func<int, int, int> Func1 = new Func<int, int, int>(calculator.Add);
Func<int, int, int> Func2 = new Func<int, int, int>(calculator.Sub);
int x = ;
int y = ;
int z = ;
z = Func1.Invoke(x, y);
Console.WriteLine(z);
z = Func2.Invoke(x, y);
Console.WriteLine(z);
}
} class Calculator
{
public int Add(int a, int b)
{
int result = a + b;
return result;
}
public int Sub(int a, int b)
{
int result = a - b;
return result;
}
}
}
在打尖括号时,IDE提示我们他有17个重载,通过下翻会发现,它会增加参数的个数(最后的那个是返回值类型),我们要用他来引用Add和Sub方法,而这两个方法有两个参数,所以我们就选了图片里的那种情况,因为两个参数是int类型,所以返回的结果也一定是int类型 所以就用 Func<int,int,int>(Calculator.Add); (尖括号里前两个是参数类型,最后一个是返回值类型)
运行结果:
自定义委托
以上的Action委托和Function委托,是微软已经为我们准备好的,那我们自己怎么声明呢,这就是接下来的自定义委托
先说明,委托是一种类(class),所以委托声明在名称空间内,和program类是平级的。如何查看委托是不是类呢,很简单的一个小程序:
namespace DelegateExample_IsClass_
{
class Program
{
static void Main(string[] args)
{
Type t = typeof(Action);
Console.WriteLine(t.IsClass);
}
}
}
结果运行后打印出来的是 True ,这说明委托确实是个类
然后我们就自己声明一个委托,委托的声明格式是这样的:
可访问性 delegate关键字 目标方法返回值类型 委托名字(目标方法的参数列表);
下面看一个小程序:
namespace DelegateExample_custom_delegate_
{
public delegate double Calc(double x,double y); class Program
{
static void Main(string[] args)
{
Calculator calculator = new Calculator();
Calc calc = new Calc(calculator.Add);
Calc calc2 = new Calc(calculator.Sub);
Calc calc3 = new Calc(calculator.Mul);
Calc calc4 = new Calc(calculator.Div); double a = ;
double b = ;
double c = ; c = calc.Invoke(a, b);
Console.WriteLine(c);
c = calc2.Invoke(a, b);
Console.WriteLine(c);
c = calc3.Invoke(a, b);
Console.WriteLine(c);
c = calc4.Invoke(a, b);
Console.WriteLine(c); }
}
class Calculator
{
public double Add(double x, double y)
{
return x + y;
}
public double Sub(double x, double y)
{
return x - y;
}
public double Mul(double x, double y)
{
return x * y;
}
public double Div(double x, double y)
{
return x / y;
}
}
}
这个程序中,我们自己声明了一个叫Calc的委托,因为我们的方法都是double的参数,double的返回值,所以是 "double Calc" 。剩下的就没什么大问题了。
自定义委托时有几点需要注意:
委托与所封装的方法必须“类型兼容”,也就是说
返回值的数据类型要一致
参数列表在个数和数据类型上一致(参数名不需要一样)
再就是声明的时候要声明在正确的位置处,要声明在名称空间中(与program平级),但是C#又允许嵌套类型存在,声明在Program类里又编译的过去,但不要这么干,该放哪就放哪(要放在名称空间里与其他类平级)
----------------------------------------------------------------------------------------------
迫于时间缘故,这篇博客就先写这么多,放假后会写完后面的
希望博友们指出我的问题所在,指出我哪里理解错了,共同交流,共同进步!
To be continued!
C#——委托(1)的更多相关文章
- HTML 事件(三) 事件流与事件委托
本篇主要介绍HTML DOM中的事件流和事件委托. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三) 事件流与事件委托 4 ...
- C#基础篇 - 理解委托和事件
1.委托 委托类似于C++中的函数指针(一个指向内存位置的指针).委托是C#中类型安全的,可以订阅一个或多个具有相同签名方法的函数指针.简单理解,委托是一种可以把函数当做参数传递的类型.很多情况下,某 ...
- [.NET] C# 知识回顾 - 委托 delegate (续)
C# 知识回顾 - 委托 delegate (续) [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6046171.html 序 上篇<C# 知识回 ...
- [C#] C# 知识回顾 - 委托 delegate
C# 知识回顾 - 委托 delegate [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6031892.html 目录 What's 委托 委托的属性 ...
- 9、委托、事件、Lambda
开始 关于委托,肯定是要有问题的. 第一个问题,委托用来干什么? 看.net中的表述:在.net平台下,委托类型用来定义和相应应用程序中的回调.(回调?处理内存中两个实体双向通信的一种技术.) 第 ...
- iOS 委托与文本输入(内容根据iOS编程编写)
文本框(UITextField) 本章节继续编辑 JXHypnoNerd .文件地址 . 首先我们继续编辑 JXHypnosisViewController.m 修改 loadView 方法,向 ...
- C#委托异步调用
参考页面: http://www.yuanjiaocheng.net/webapi/mvc-consume-webapi-get.html http://www.yuanjiaocheng.net/w ...
- JavaScript事件代理和委托(Delegation)
JavaScript事件代理 首先介绍一下JavaScript的事件代理.事件代理在JS世界中一个非常有用也很有趣的功能.当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委 ...
- .NET面试题系列[7] - 委托与事件
委托和事件 委托在C#中具有无比重要的地位. C#中的委托可以说俯拾即是,从LINQ中的lambda表达式到(包括但不限于)winform,wpf中的各种事件都有着委托的身影.C#中如果没有了事件,那 ...
- .NET基础拾遗(4)委托、事件、反射与特性
Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...
随机推荐
- restlet验证
1 restlet有无认证对比 无认证: 客户端发起请求 -----> 服务器路由 -----> 访问服务端资源 有认证: 客户端发起请求 -----> 认证 ----->服务 ...
- 箭头函数 this arrow function 无this
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions import w ...
- 使用服务端的临时密钥,不依赖阿里js的putFIle--》阿里oss
<!DOCTYPE html> <html lang='en'> <head> <meta charset='UTF-8'> <title> ...
- substr扩展版:支持中文字符串截取
function d_substr($str, $start=0, $length, $charset="utf-8", $suffix=true) { if(function_e ...
- iOS 流布局 UICollectionView使用(UICollectionVIew的代理方法)
UICollectionViewDataSource协议 这个协议主要用于collectionView相关数据的处理,包含方法如下: 设置分区数(这个是可选实现的) - (NSInteger)numb ...
- SecureCRT连接VMWare中Linux
SecureCRT连接vmvare虚拟机ubuntu的前提条件1. 使用主机可以ping通虚拟机,或虚拟机可以ping通主机2. 虚拟机已经开启ssh服务,可以使用sudo apt-get i ...
- 序列化组件(get/put/delete接口设计),视图优化组件
一 . 知识点回顾 1 . 混入类 , 多继承 class Animal(object): def eat(self): print("Eat") def walk(self): ...
- 原生Base64编码/解码(OC与Swift)
Objective-C NSString *plainString = @"foo"; Encoding NSData *plainData = [plainString data ...
- 各种 Spring-Boot-Starters系列 介绍
分类: JavaWeb后端(6) 目录(?)[+] 原文传送门:Spring Boot application starters ↑传送门里有各Spring-Boot-Starters ...
- UTCformat 转换UTC时间并格式化成本地时间
/** * UTCformat 转换UTC时间并格式化成本地时间 * @param {string} utc */ UTCformat (utc) { var date = new Date(utc) ...