什么是委托?
还记得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)的更多相关文章

  1. HTML 事件(三) 事件流与事件委托

    本篇主要介绍HTML DOM中的事件流和事件委托. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三) 事件流与事件委托 4 ...

  2. C#基础篇 - 理解委托和事件

    1.委托 委托类似于C++中的函数指针(一个指向内存位置的指针).委托是C#中类型安全的,可以订阅一个或多个具有相同签名方法的函数指针.简单理解,委托是一种可以把函数当做参数传递的类型.很多情况下,某 ...

  3. [.NET] C# 知识回顾 - 委托 delegate (续)

    C# 知识回顾 - 委托 delegate (续) [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6046171.html 序 上篇<C# 知识回 ...

  4. [C#] C# 知识回顾 - 委托 delegate

    C# 知识回顾 - 委托 delegate [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6031892.html 目录 What's 委托 委托的属性 ...

  5. 9、委托、事件、Lambda

    开始 关于委托,肯定是要有问题的. 第一个问题,委托用来干什么? 看.net中的表述:在.net平台下,委托类型用来定义和相应应用程序中的回调.(回调?处理内存中两个实体双向通信的一种技术.)   第 ...

  6. iOS 委托与文本输入(内容根据iOS编程编写)

    文本框(UITextField) 本章节继续编辑 JXHypnoNerd .文件地址 . 首先我们继续编辑  JXHypnosisViewController.m 修改  loadView 方法,向  ...

  7. C#委托异步调用

    参考页面: http://www.yuanjiaocheng.net/webapi/mvc-consume-webapi-get.html http://www.yuanjiaocheng.net/w ...

  8. JavaScript事件代理和委托(Delegation)

    JavaScript事件代理 首先介绍一下JavaScript的事件代理.事件代理在JS世界中一个非常有用也很有趣的功能.当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委 ...

  9. .NET面试题系列[7] - 委托与事件

    委托和事件 委托在C#中具有无比重要的地位. C#中的委托可以说俯拾即是,从LINQ中的lambda表达式到(包括但不限于)winform,wpf中的各种事件都有着委托的身影.C#中如果没有了事件,那 ...

  10. .NET基础拾遗(4)委托、事件、反射与特性

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...

随机推荐

  1. notHere 对框架解决方案的框架预期处理

    <script> import wepy from 'wepy' import api from '../api/api' import util from '../utils/util' ...

  2. ES5中的类与继承

    最近在重新复习TypeScript,看到类这块的时候自然会和ES5中的类写法进行对比加深印象. 发现ES5的类与继承一些细节还是挺多的,时间久了容易忘记,特此记录下. 首先是ES5的类定义,这没什么好 ...

  3. 【题解】 P1092虫食算

    [题解]P1092 虫食算 老题了,很经典. 用到了一些搜索套路. 可行性剪枝,劣者靠后,随机化,\(etc......\) 搜索设参也很有技巧,设一个\(adjustment\)参数可以很方便地在两 ...

  4. 题解 P3372 【【模板】线段树 1】

    发一篇不需要O2就能过的分块. 基本思路: 分块的思路,大段维护,小段朴素. 维护几个数组: 区块\(block[maxn]\) 懒标记\(tag[maxn]\) 真实数据\(data[maxn]\) ...

  5. 洛谷 2868 [USACO07DEC]观光奶牛Sightseeing Cows

    题目戳这里 一句话题意 L个点,P条有向边,求图中最大比率环(权值(Fun)与长度(Tim)的比率最大的环). Solution 巨说这是0/1分数规划. 话说 0/1分数规划 是真的难,但貌似有一些 ...

  6. 【Android】Android中AlertDialog对话框的使用实例

    package com.ceac.deng; import android.R.string; import android.support.v7.app.ActionBarActivity; imp ...

  7. iOS本地数据存取,看这里就够了

    本文授权转载,作者:hosea_zhou(简书) 应用沙盒 1)每个iOS应用都有自己的应用沙盒(应用沙盒就是文件系统目录),与其他文件系统隔离.应用必须待在自己的沙盒里,其他应用不能访问该沙盒 2) ...

  8. c语言学习的第11天 指针

    #include<stdio.h> int main(void) { int * p; int i=3; int j; p=&i; j=*p; printf("i=%d, ...

  9. tkinter之canvas(画布)

    画布的例子: from tkinter import * root=Tk() root.title('简易绘图') can=Canvas(root,width=400,height=300,bg='# ...

  10. PHP的引用详解【转】

    摘自:http://www.cnblogs.com/xiaochaohuashengmi/archive/2011/09/10/2173092.html 官方文档: 1.引用是什么:http://ww ...