当前位置:
首页 > 编程开发 > Objective-C编程 >
-
c#3.0入门第一章 Lambda表达式第四节Lambda的用途&类型声明能够和不能够省略的地
制作者:剑锋冷月 单位:无忧统计网,www.51stat.net 成问题的是,虽然为了源代码的简洁性,很想用Lambda表达式,但是要写的代码却不能全部都用Lambda表达式来写。
那么, Lambda表达式究竟能做到什么程度呢?
习惯了C/C++编程风格的程序员,一定以为因C#语法与之很相似,所以用C#编写相对复杂的程序应该也没有问题。可是很遗憾,情况不是这样。那是因为C/C++具有能写出复杂功能的表达式的逗号表达式,而C#却没有。
例如,C/C++中,下面的代码是可行的。
int a,b,c;
c = (a=1, b=2, a+b); // a=1、b=2、c=a + b
printf("%d\n",c);
正因为仅仅一个表达式就能做相当多的处理,所有逗号表达式才有着重要的意义。
但是,C#却没有这样的用法。
但是C#有三元运算符?:和空接合运算符??。通过使用这些运算符,相当数量的代码都可以用Lambda表达式来写了。
例如,“根据参数指定的文件名向文件中写入字符串,参数为null的情况下,用‘default.txt’作为默认文件名”这样的Lambda表达式,像下面那样,用空接合运算符??就可以用Lambda表达式来写。
using System;
class Program
{
static void Main(string[] args)
{
Action<string> method =
(filename) => System.IO File.WriteAllText(
filename ?? "default.txt", "Hello!");
method(null); // 生成default.txt
method("hello.txt"); // 生成hello.txt
}
}
List11 使用了空接合运算符??的Lambda表达式
或者“参数的flag如果是false的话,文件名就是‘normal.log’,true的话就是‘system.log’”的情况下,使用三元运算符(?:)按照如下的方式以表达式形式的Lambda来写。
编缉推荐阅读以下文章
[C# 3.0 入门] [第一章 Lambda表达式] 第五节:Lambda表达式的使用范例 & Lambda表达式的各种变体
[C# 3.0 入门] [第一章 Lambda表达式] 第三节:Lambda与匿名方法的区别
[C# 3.0 入门] [第一章 Lambda表达式] 第二节:Lambda表达式带来了什么
[C# 3.0 入门] [第一章 Lambda表达式] 第一节:C# 3.0 是什么 & C# 3.0的适用范围
C# 3.0 入门系列(一)
using System;
class Program
{
static void Main(string[] args)
{
Action<bool> method =
(system) => System.IO.File.AppendAllText(
system ? "system.log" : "normal.log", "log message\r\n");
method(false); // 生成normal.log
method(true); // 生成system.log
}
}
List12 使用三元运算符(?:)的Lambda表达式
但是,前一章的List10的例子里,其中的if语句中就不能改用三元运算符来替换。如果试图替换的话就是以下情况:
using System;
class Program
{
static void Main(string[] args)
{
Action<string> method = (filename) =>
filename == null
? Console.WriteLine("Hello!")
: System.IO.File.WriteAllText(filename, "Hello!");
method(null);
method("hello.txt");
}
}
List13 List10中用三元运算符改写后(产生编译错误)
这个代码,会产生以下的编译错误:
error CS0201: 只有 assignment、call、increment、decrement 和 new 对象表达式可用作语句。
error CS0173: 无法确定条件表达式的类型,因为“void”和“void”之间没有隐式转换。
这并不是说Lambda表达式不能调用具有void返回值的方法。下面的代码就没有问题。
Action<string> method =
(filename) => System.IO.File.WriteAllText(filename, "Hello!");
编缉推荐阅读以下文章
[C# 3.0 入门] [第一章 Lambda表达式] 第五节:Lambda表达式的使用范例 & Lambda表达式的各种变体
[C# 3.0 入门] [第一章 Lambda表达式] 第三节:Lambda与匿名方法的区别
[C# 3.0 入门] [第一章 Lambda表达式] 第二节:Lambda表达式带来了什么
[C# 3.0 入门] [第一章 Lambda表达式] 第一节:C# 3.0 是什么 & C# 3.0的适用范围
C# 3.0 入门系列(一)
这里产生error的原因是,三元运算符的第二个、第三个运算数不能写成void类型的表达式(因为这样写,void没法隐式转换成第二个、第三个运算数的类型,所以整个表达式的类型就无法判断了。
因为存在这样的问题,有void类型的返回值的表达式情况下,三元运算符使用就很困难。其实,void返回值的表达式很难理解,不能写反而是个好事。
除了void型以外,其它类型的表达式,使用三元运算符就没有问题。下面的代码在编译和执行时就没有问题。
1using System;
2
3class Program
4{
5 static void Main(string[] args)
6 {
7 Func<int, bool> method = (year) =>
8 year < 1994 ? year % 4 == 0 : year % 4 == 2;
9
10 Console.WriteLine("冬奥会年份");
11 for (int i = 1988; i < 1999; i++)
12 {
13 Console.WriteLine("{0}年={1}", i, method(i));
14 }
15 // 输出:
16 // 冬奥会年份
17 // 1988年=True
18 // 1989年=False
19 // 1990年=False
20 // 1991年=False
21 // 1992年=True
22 // 1993年=False
23 // 1994年=True
24 // 1995年=False
25 // 1996年=False
26 // 1997年=False
27 // 1998年=True
28 }
29}
30
List14 使用三元运算符的Lambda表达式
代入变量method的Lambda表达式,判断参数的年份是不是冬奥会举行的年份,1994年以后,因为是两年举行一届,所以判断方式也要改变。这种情况下,当然是三元运算符派上用场的时候。总之,这种程度的问题,用表达式形式的Lambda就比较容易写。
编缉推荐阅读以下文章
[C# 3.0 入门] [第一章 Lambda表达式] 第五节:Lambda表达式的使用范例 & Lambda表达式的各种变体
[C# 3.0 入门] [第一章 Lambda表达式] 第三节:Lambda与匿名方法的区别
[C# 3.0 入门] [第一章 Lambda表达式] 第二节:Lambda表达式带来了什么
[C# 3.0 入门] [第一章 Lambda表达式] 第一节:C# 3.0 是什么 & C# 3.0的适用范围
C# 3.0 入门系列(一)
不用类型声明的情况和必须类型声明的情况
大部分情况下,Lambda表达式的参数类型都可以省略。然而,Lambda表达式的使用也存在限制,不能推定出类型的情况下就不能用Lambda表达式。
例如,Lambda表达式就不能代入到使用var关键字隐式类型声明的局部变量:
var Lambda = (int x) =>x *2;
上面的代码会产生“Lambda表达式局部变量隐式的类型声明不会起作用”的错误。避免错误的方法是不要用var,而是明确的进行类型声明。
然而,
下面的例子
1using System;
2
3delegate int delegate1( int x );
4delegate int delegate2( string s );
5
6class Program
7{
8 private static void sample(delegate1 method)
9 {
10 Console.WriteLine("void Sample(delegate1 method)");
11 }
12
13 private static void sample(delegate2 method)
14 {
15 Console.WriteLine("void Sample(delegate2 method)");
16 }
17
18 static void Main(string[] args)
19 {
20 sample((int x) => 0);
21 // sample((x) => 0); // 如果没有参数类型声明会产生错误
22 }
23}
24
List 15 必须指定参数类型的情况
这个例子中,“sample((x)=> 0”会产生编译错误。满足条件的sample方法有两个,所有就不能确定究竟应该使用哪个。然而,在参数前加上类型声明“sample((int x) => 0”,就能够编译执行。因为参数类型的指定,在2个sample方法中,有一个与之类型相吻合,所以以此为依据就能够选择了。
编缉推荐阅读以下文章
[C# 3.0 入门] [第一章 Lambda表达式] 第五节:Lambda表达式的使用范例 & Lambda表达式的各种变体
[C# 3.0 入门] [第一章 Lambda表达式] 第三节:Lambda与匿名方法的区别
[C# 3.0 入门] [第一章 Lambda表达式] 第二节:Lambda表达式带来了什么
[C# 3.0 入门] [第一章 Lambda表达式] 第一节:C# 3.0 是什么 & C# 3.0的适用范围
C# 3.0 入门系列(一)
什么都不做的Lambda表达式
这个话题说到此,还有盲点。这里先说明一下什么都不做的Lambda表达式的写法。
Lambda表达式没有返回值的情况(void的情况),想使其内容为空的情况下(调用后什么也不执行的Lambda表达式选择使用的情况),可以使用内容为空的Lambda语句。
例如,下面这个的Lambda表达式:
(x) => { };
这样用Lambda表达式重构,解决了“引入了null值对象”的问题。一句话,不应该用null表示什么也不做的表达式,而是采用调空Lambda表达式的手法。
简单的说,分别用代码来展示能够使用和不能够使用这个技术的场合。
首先,说说不能够使用该技术的场合。下面的代码,因为什么也不需要处理,所以用null值表示的例子。Sample方法的参数action,仅在值不为null的情况下被调用。
using System;
class Program
{
private static void Sample(Action<string> action)
{
if (action != null) action("Hello!");
}
static void Main(string[] args)
{
Action<string> action = null;
Sample(action);
action = (x) => Console.WriteLine(x);
Sample(action); // 输出:Hello!
}
}
List 16 执行时没什么可处理的情况下用null表示的例子
相反,下面的代码,在没什么要执行的情况下,要使用空Lambda表达式表示的情况。没必要判定Sample方法的参数action是否为null。如果需要处理的内容不存在的情况下,仅仅用空的Lambda表达式来执行,什么也不做就返回。
using System;
class Program
{
private static void Sample(Action<string> action)
{
action("Hello!");
}
static void Main(string[] args)
{
Action<string> action = (x) => { };
Sample(action);
action = (x) => Console.WriteLine(x);
Sample(action); // 输出:Hello!
}
}
List 17 没什么可处理的情况下用空表达式的例子
这样的“什么也不做的Lambda表达式(或是以前的匿名方法)”,是笔者经常使用的技术。
例如,现在正在写的程序,具有用户的操作用报表的形式回放的功能,通过该功能进行自动测试。这个时候,回放中与输出有关的处理会全部禁用,以提高其运行效率。这些操作的实现,并不需要具有输出功能的方法对条件进行一个一个的判断,只要用“空Lambda表达式(匿名方法)”就行了。因此,源代码仍然能够维持其简洁,成功实现了随时都能够执行的自动测试效率的目的。
编缉推荐阅读以下文章
[C# 3.0 入门] [第一章 Lambda表达式] 第五节:Lambda表达式的使用范例 & Lambda表达式的各种变体
[C# 3.0 入门] [第一章 Lambda表达式] 第三节:Lambda与匿名方法的区别
[C# 3.0 入门] [第一章 Lambda表达式] 第二节:Lambda表达式带来了什么
[C# 3.0 入门] [第一章 Lambda表达式] 第一节:C# 3.0 是什么 & C# 3.0的适用范围
C# 3.0 入门系列(一)
using System;
class Program
{
static void Main(string[] args)
{
Action<bool> method =
(system) => System.IO.File.AppendAllText(
system ? "system.log" : "normal.log", "log message\r\n");
method(false); // 生成normal.log
method(true); // 生成system.log
}
}
List12 使用三元运算符(?:)的Lambda表达式
但是,前一章的List10的例子里,其中的if语句中就不能改用三元运算符来替换。如果试图替换的话就是以下情况:
using System;
class Program
{
static void Main(string[] args)
{
Action<string> method = (filename) =>
filename == null
? Console.WriteLine("Hello!")
: System.IO.File.WriteAllText(filename, "Hello!");
method(null);
method("hello.txt");
}
}
List13 List10中用三元运算符改写后(产生编译错误)
这个代码,会产生以下的编译错误:
error CS0201: 只有 assignment、call、increment、decrement 和 new 对象表达式可用作语句。
error CS0173: 无法确定条件表达式的类型,因为“void”和“void”之间没有隐式转换。
这并不是说Lambda表达式不能调用具有void返回值的方法。下面的代码就没有问题。
Action<string> method =
(filename) => System.IO.File.WriteAllText(filename, "Hello!");
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
SQL Server -- 解决存储过程传入参数作为s
JavaScript判断两个数组相等的四类方法
js如何操作video标签
React实战--利用甘特图和看板,强化Paas平
【记录】正则替换的偏方
前端下载 Blob 类型整理
抽象语法树AST必知必会
关于JS定时器的整理
JS中使用Promise.all控制所有的异步请求都完
js中字符串的方法
import-local执行流程与node模块路径解析流程