C# 匿名方法
每次写博客,第一句话都是这样的:程序员很苦逼,除了会写程序,还得会写博客!当然,希望将来的一天,某位老板看到此博客,给你的程序员职工加点薪资吧!因为程序员的世界除了苦逼就是沉默。我眼中的程序员大多都不爱说话,默默承受着编程的巨大压力,除了技术上的交流外,他们不愿意也不擅长和别人交流,更不乐意任何人走进他们的内心,他们常常一个人宅在家中!
废话说多了,咱进入正题:
上一节我们谈到了匿名变量,本节我们学习匿名方法。
来自MSDN上的说法是这样的
在 2.0 之前的 C# 版本中,声明委托的唯一方法是使用命名方法。 C# 2.0 引入了匿名方法,而在 C# 3.0 及更高版本中,Lambda 表达式取代了匿名方法,作为编写内联代码的首选方式。 有一种情况下,匿名方法提供了 Lambda 表达式中所没有的功能。 您可使用匿名方法来忽略参数列表。 这意味着匿名方法可转换为具有各种签名的委托。 这对于 Lambda 表达式来说是不可能的。 有关 lambda 表达式的更多特定信息,请参见 Lambda 表达式(C# 编程指南)。
根据MSDN上的说法,我们知道先有委托,再有匿名方法,最后到Lanbda表达式。因此,在讲解C#匿名方法之前,我们有必要说说C#委托这个东东。
委托是一个类型安全的对象,它指向程序中另一个以后会被调用的方法(或多个方法)。通俗的说,委托是一个可以引用方法的对象,当创建一个委托,也就创建一个引用方法的对象,进而就可以调用那个方法,即委托可以调用它所指的方法。
- 如何使用委托?
1、定义委托类型
[访问修饰符]delegate 返回类型 委托名(形参);
2、声明委托对象
委托名 委托实例名;
3、创建委托对象(确定与哪些方法进行绑定)
委托实例名=new 委托名(某个类的方法)
4、使用委托调用方法
委托实例名(实参)
- 委托注意事项:
1、委托和方法必须具有相同的参数。
2、委托可以调用多个方法,即一个委托对象可以维护一个可调用方法的列表而不是单独的一个方法,称为多路广播(多播)。
3、使用+=和-=运算实现方法的增加和减少
下面我们通过一个小例子来讲解下委托,其代码如下(本事例通过计算器(+-*/)讲解简单的委托):
delegate int calculator(int x, int y); //委托类型
static void Main(string[] args)
{
//创建委托对象(确定与哪些方法进行绑定),委托实例名=new 委托名(某个类的方法,本例与加法向绑定
calculator MYAdd = new calculator(Adding);
//创建委托对象(确定与哪些方法进行绑定),委托实例名=new 委托名(某个类的方法,本例与减法向绑定
calculator MYMove = new calculator(Moveing);
//创建委托对象(确定与哪些方法进行绑定),委托实例名=new 委托名(某个类的方法,本例与乘法向绑定
calculator MYMultiply = new calculator(Multiply);
//创建委托对象(确定与哪些方法进行绑定),委托实例名=new 委托名(某个类的方法,本例与除法向绑定
calculator MYDivide = new calculator(Divide);
//通过委托执行方法
int A = MYAdd(, );//
int B = MYMove(, );//
int C = MYMultiply(, );//
int D = MYDivide(, );//
} /// <summary>
/// 加法
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public static int Adding(int x,int y)
{
return x + y;
}
/// <summary>
/// 减法
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public static int Moveing(int x, int y)
{
return x - y;
}
/// <summary>
/// 乘法
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public static int Multiply(int x, int y)
{
return x * y;
}
/// <summary>
/// 除法
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public static int Divide(int x, int y)
{
return x / y;
}
根据上述的事例,大家应该了解简单委托的使用了。
那么,我们更近一步,来说说泛型委托。泛型应该是大家比较熟悉的一种数据类型,泛型委托又是如何和泛型向结合的呢?
再讲泛型委托之前,先说说微软引入泛型的目的及使用泛型的好处。
- 为什么要有泛型
- 假设你是一个方法的设计者,
- 这个方法有一个传入参数,有一个返回值。
- 但你并不知道这个参数和返回值是什么类型的,
- 如果没有泛型,你可能把参数和返回值的类型都设定为Object了
- 那时,你心里肯定在想:反正一切都是对象,一切的基类都是Object
- 没错!你是对的!
- 这个方法的消费者,会把他的对象传进来(有可能会做一次装箱操作)
- 并且得到一个Object的返回值,他再把这个返回值强制类型转化为他需要的类型
- 那么这个过程涉及到的装箱拆箱会损耗系统的性能。
- 那么我们如何把损耗性能避免掉呢?
- 有泛型之后就可以了!
微软已经为我们事先定义好了三个泛型委托(Predicate,Action,Func),下面我们探讨下这三个委托的不同。
1、Predicate 泛型委托定义如下:
public delegate bool Predicate<in T>(T obj);
这个委托表示的方法需要传入一个T类型的参数,并且需要返回一个bool类型的返回值
代码实例如下:、
static void Main(string[] args)
{
//Predicate 泛型委托代表一类具有 一个T类型(通用类型)作为参数并返回BOOL类型的方法
var B = new Predicate<int>(isbol);
bool BB=isbol(1);//true
} /// <summary>
/// Predicate 泛型委托
/// </summary>
/// <typeparam name="?"></typeparam>
/// <param name="x"></param>
/// <returns></returns>
public static bool isbol(int x)
{
return x > ;
}
2、Action委托定义如下:
public delegate void Action<T>(T obj,T obj2,...,obj16); --最多16个参数
他代表了一类方法,可以有0个到16个输入参数,输入参数的类型是不确定的。此类方法不能有返回值,也就是返回VOID类型的方法。
代码实例如下:
static void Main(string[] args)
{
//Action 他代表了一类方法,可以有0个到16个输入参数,输入参数的类型是不确定的。此类方法不能有返回值,也就是返回VOID类型的方法。
var B = new Action<int,string,string>(Action_d);
B(-,"true","flase");
Console.ReadKey();
} /// <summary>
/// Action 泛型委托
/// </summary>
/// <typeparam name="?"></typeparam>
/// <param name="x"></param>
/// <returns></returns>
public static void Action_d(int x,string y,string z)
{
if (x > )
{
Console.WriteLine(y);
}
else
{
Console.WriteLine(z);
}
}
3、Func泛型委托 定义如下:
public delegate T Func<T>(T obj,T obj2,...,obj16); --最多16个参数
为了弥补Action泛型委托,不能返回值的不足,.net提供了Func泛型委托,相同的是它也是最多0到16个输入参数,参数类型由使用者确定,不同的是它规定要有一个返回值,返回值的类型也由使用者确定,说白了,就是ACtion委托没有返回值,而FUNC委托具有了返回值,他们都是最多16个参数。
代码实例如下:
static void Main(string[] args)
{
//Func 他代表了一类方法,可以有0个到16个输入参数,输入参数的类型是不确定的。此类方法有返回值。
var B = new Func<int, string,string,string>(Func_d);//注意:<>中最后一个string代表输出类型
Console.WriteLine(B(,"True","False"));
Console.ReadKey();
} /// <summary>
/// Predicate 泛型委托
/// </summary>
/// <typeparam name="?"></typeparam>
/// <param name="x"></param>
/// <returns></returns>
public static string Func_d(int x,string y,string z)
{
if (x > )
{
return y;
}
else
{
return z;
}
}
学会了C#委托,那么C#匿名方法就显得很简单了!下面和小伙伴们探讨下C#匿名方法的使用!
还记得本篇上述的计算器吧!就是那个加减乘除委托。我们知道,我们在定义好委托后,还需要在定义加减乘数方法,C#引入匿名方法后,我们就不需要在单独写这些方法了,我们只需在匿名方法体内实现我们的业务逻辑即可!
delegate int calculator(int x, int y); //委托类型
static void Main(string[] args)
{
//创建委托对象(确定与哪些方法进行绑定),委托实例名=new 委托名(某个类的方法,本例与加法向绑定
calculator Adding =delegate( int x, int y)
{
return x+y;
}; calculator Moveing = delegate(int x, int y)
{
return x - y;
}; calculator Multiply = delegate(int x, int y)
{
return x * y;
}; calculator Divide = delegate(int x, int y)
{
return x / y;
};
Adding(, );//
Moveing(, );//
Multiply(, );//
Divide(, );//
}
讲解到现在,想必大家对匿名方法有一定的了解了!
下面是参考MSDN上的一些资料如下:
通过使用匿名方法,由于您不必创建单独的方法,因此减少了实例化委托所需的编码系统开销。
例如,如果创建方法所需的系统开销是不必要的,则指定代码块(而不是委托)可能非常有用。 启动新线程即是一个很好的示例。 无需为委托创建更多方法,线程类即可创建一个线程并且包含该线程执行的代码。
void StartThread()
{
System.Threading.Thread t1 = new System.Threading.Thread
(delegate()
{
System.Console.Write("Hello, ");
System.Console.WriteLine("World!");
});
t1.Start();
}
匿名方法的参数的范围是“匿名方法块”。
如果目标在块外部,那么,在匿名方法块内使用跳转语句(如 goto、break 或 continue)是错误的。 如果目标在块内部,在匿名方法块外部使用跳转语句(如 goto、break 或 continue)也是错误的。
如果局部变量和参数的范围包含匿名方法声明,则该局部变量和参数称为该匿名方法的“外部”变量。 例如,下面代码段中的 n 即是一个外部变量:
int n = 0;
Del d = delegate() { System.Console.WriteLine("Copy #:{0}", ++n); };
外部变量的引用n被认为是捕获在创建委托时。 与本地变量不同,捕获的变量的生存期内扩展,直到引用该匿名方法委托被垃圾回收。
在“匿名方法块”中不能访问任何不安全代码。
在 is 运算符的左侧不允许使用匿名方法。
好了,截止到现在,匿名方法讲解完毕,如果需要更深入的了解匿名方法,可以找度娘哈!这里仅仅只是简单的介绍!
下一节,我们共同学习拉姆达表达式!lambda说: 一步一个脚印,学好C#基础很重要!
@陈卧龙的博客
C# 匿名方法的更多相关文章
- [C#] C# 基础回顾 - 匿名方法
C# 基础回顾 - 匿名方法 目录 简介 匿名方法的参数使用范围 委托示例 简介 在 C# 2.0 之前的版本中,我们创建委托的唯一形式 -- 命名方法. 而 C# 2.0 -- 引进了匿名方法,在 ...
- 用五分钟重温委托,匿名方法,Lambda,泛型委托,表达式树
这些对老一代的程序员都是老生常谈的东西,没什么新意,对新生代的程序员却充满着魅力.曾经新生代,好多都经过漫长的学习,理解,实践才能掌握委托,表达式树这些应用.今天我尝试用简单的方法叙述一下,让大家在五 ...
- 匹夫细说C#:委托的简化语法,聊聊匿名方法和闭包
0x00 前言 通过上一篇博客<匹夫细说C#:庖丁解牛聊委托,那些编译器藏的和U3D给的>的内容,我们实现了使用委托来构建我们自己的消息系统的过程.但是在日常的开发中,仍然有很多开发者因为 ...
- 从匿名方法到 Lambda 表达式的推演过程
Lambda 表达式是一种可用于创建委托或表达式目录树类型的匿名函数. 通过使用 lambda 表达式,可以写入可作为参数传递或作为函数调用值返回的本地函数. 以上是msdn官网对Lambda 表达式 ...
- C#中的匿名方法
C#中的匿名方法是在C#2.0引入的,它终结了C#2.0之前版本声明委托的唯一方法是使用命名方法的时代.虽然在 C# 3.0 及更高版本中,Lambda 表达式取代了匿名方法,作为编写内联代码的首选方 ...
- .NET中那些所谓的新语法之二:匿名类、匿名方法与扩展方法
开篇:在上一篇中,我们了解了自动属性.隐式类型.自动初始化器等所谓的新语法,这一篇我们继续征程,看看匿名类.匿名方法以及常用的扩展方法.虽然,都是很常见的东西,但是未必我们都明白其中蕴含的奥妙.所以, ...
- 匿名方法与Lambda表达式
1.匿名方法 在学习委托时,我们知道委托实例至少要绑定一个方法才能使用,而调用委托实际上是调用了它所关联地方法.一般来说,需要定义一个与委托签名相符的方法,并使之与委托变量关联.如以下代码: Acti ...
- 委托学习笔记后续:泛型委托及委托中所涉及到匿名方法、Lambda表达式
引言: 最初学习c#时,感觉委托.事件这块很难,其中在学习的过程中还写了一篇学习笔记:委托.事件学习笔记.今天重新温故委托.事件,并且把最近学习到和委托相关的匿名方法.Lambda表达式及泛型委托记录 ...
- 30天C#基础巩固-----值类型/引用类型,泛型,空合并操作符(??),匿名方法
一:值类型/引用类型的区别 值类型主要包括简单类型,枚举类型,和结构体类型等,值类型的实例通常被分配在线程堆栈上面变量保存的内容是实例数据本身.引用类型被分配在托管堆上,变量保存的是地址.引 ...
- C#的匿名方法
匿名方法是在初始化委托时内联声明的方法. 例如下面这两个例子: 不使用匿名方法的委托: using System; using System.Collections.Generic; using Sy ...
随机推荐
- 简单排序算法 C++类实现
简单排序算法: 冒泡排序 插入排序 选择排序 .h代码: // // SortClass.h // sort and selection // // Created by wasdns on 16/1 ...
- 专治XP正在启动就蓝屏重启一直循环
我5月6号发帖求助,很多同行都要说换系统.PE修复启动项等,这些早在我入行电脑行业10年前都会的.但是客户的数据是用金钱也买不到的,不能就这样给换了吧,这样也让客户小看我们搞电脑行业的了. 好说正题: ...
- wordpress 常用函数 checked(),selected(),disabled()
checked().selected().disabled(),这三个函数是主题设计和插件设计中添加后台设置比较常用到的函数. 例如自定义一个widget,这个widget有一个字段为文章排列方式.文 ...
- Class Abstraction -- Object Interfaces
<?php /* PHP 5 introduces abstract classes and methods. Classes defined as abstract may not be in ...
- 模板-高精度BigInteger
#include <bits/stdc++.h> using namespace std; struct BigInteger { static const int BASE = 1000 ...
- java中重载和覆盖(又称重写)的区别
初次见到这两个单词并没有什么特别的感觉,但是时间长了,却发现书上一会儿用override,一会儿又用overload,搞得我的迷迷糊.于是就做了个总结,希望能对和我一样对这两个概念模糊不清的网友有一个 ...
- ServletDemo
1. Servlet 接口 继承 Servlet 接口,实现Servlet 接口的 所有抽象方法! 实现类代码 package xw.servlet; import java.io.IOExcepti ...
- ajax例子:审核验证用户名;登录界面
审核验证用户名主页面: <body><div>用户名:<input type="text" id="uid" /><s ...
- MessageQueue 一 简单的创建和读取
创建一个队列,并写入数据 在读取出来 using System; using System.Collections.Generic; using System.Linq; using System.M ...
- 【Android开发学习笔记】【第八课】五大布局-下
概念 五大布局上一篇文章已经介绍了 LinearLayout RelativeLayout 这一篇我们介绍剩下的三种布局 FrameLayout 五种布局中最佳单的一种布局.在这个布局在整个界面被当成 ...