C#高级技师语法,你会吗?

孤街浪徒 提交于 2021-02-19 12:09:58
【导读】呀,最近太忙了,没什么时间去看和学习,既然长篇文章一时半会吐不出来,短篇还是可以搞搞,操作系统绝不会断更。本文我们来搞点C#中高逼格语法。


=>这玩意从C#6开始支持方法,运算符和只读属性的表达式主体定义。从C#7.0开始支持构造函数,终结器以及属性和索引器访问器的表达式主体定义。所以本文来讲讲=>运算符


高级语法


我们正常写一个方法,都是很明确的方法主体,我们称之为“块主体”,比如如下

static string Say()
{
    return "Hello World";
}

用了=>运算符,我们可以将上述方法简化到极致

Console.WriteLine(Say());
static string Say() => "Hello World";

如上就通过=>运算符隐式转换为方法主体的返回类型,最终还是翻译成第一种写法。


C#中的lambda表达式绝对秒杀Java,用过Java我也是这么认为,不服可以一战,我们看用过最多的大概是对集合的处理,集合中内置使用几种委托,继而委托简化为lambda,比如如如下Where过滤条件调用Func委托

var list = new List<string>() { "h""e""l""l""o" };
list = list.Where(d => d.Equals("o")).ToList();


要是到这里就结束,那么本文也发表不出来,公众号文章必须至少要300字(不算任何标点符号、空格、图片等等),所以我要极力凑满至少300字


开玩笑哈,每写一篇我都竭尽所能希望能让各位童鞋能有所收获,尽管可能每一篇不是那么都尽人意,进入话题正轨


上述只是最基础的铺垫,要是这个语法都不知晓,那这......就不用往下看了,先补补基础知识再继续本文接下来的内容


上述我们讲解了=>运算符和内置泛型委托,我们看到更多的是将委托作为方法参数来使用,将委托作为方法参数或返回值也是可行dei,比如如下:

static Func<longintDefaultDelayInSecondsByAttemptFuncOne()
{
 return (attempt) =>
 {
  var random = new Random();
  return (int)Math.Round(
   Math.Pow(attempt - 14) + 15 + random.Next(30) * attempt);
 };
}

定义如上方法后,我们该如何调用呢?你要是会用lambda,那么此种方法调用自然不在话下

var func = DefaultDelayInSecondsByAttemptFuncOne();
Console.WriteLine(func(2));

要是上述方法看不懂,那这.....请折返,那就需要回顾并巩固下基础,这里顺便提一下关于变量定义的问题,有些极力建议不要使用var,比如上述你一眼压根看不出返回类型是啥,只有将鼠标放上去才知道返回的是一个委托,有些用var(比如我)是为了方便,所以这里看个人使用习惯,没有绝对的好与坏


接下来我们再对此方法进行改造,看看该方法的另外一个变体版本

static readonly Func<longint> DefaultDelayInSecondsByAttemptFuncTwo = attempt =>
{
 var random = new Random();
 return (int)Math.Round(
  Math.Pow(attempt - 14) + 15 + random.Next(30) * attempt);
};

第一眼看起来和第一种定义方式相差无几,我也是这么认为,那么调用该方法和第一种调用是一样的吗?默思一秒,答案:不一样

var result = DefaultDelayInSecondsByAttemptFuncTwo(2);
Console.WriteLine(result);

变体之后的方法调用和我们正常进行方法调用一样,但第一种方式则是返回方法的引用,二者看起来差不多,但是区别还是很大


不知道你注意到了没有,二者还有一个很大的区别,变体方法使用了readonly修饰符,而第一种方式则不能使用该修饰符,是不是又涨知识了呢?


我相信你写过的绝大多数方法都无法使用readonly修饰符(编译报错),所以有面试官问了很偏门的问题,方法支持使用readonly修饰符吗?看过本文后,应毫不犹豫的回答:支持


上述变体方法支持readonly,其本质其实是字段

public static readonly Func<string> Variable1 = () => "Hello";


那么问题来了,有的童鞋就疑惑了,那为什么第一种方式就不支持呢?因为第一种方法返回的是方法引用,这样的答案就好比“标准”解题老师


很显然没有很强的说服力,自问自答,自己骗自己,要是我们如下这样为何就不支持呢?

static readonly string Say() => "Hello World";


至于为何不支持的本质,这个问题就留给大家去探讨吧,至少就目前而言,好像只有上述变体方式支持readonly修饰符,若有深层次见解,欢迎留言


重点来了,又到了,分析本质的时候了


我们看看第一种返回委托的方法大致会翻译成什么呢?别担心,很简单,你看的懂

private static Func<longintDefaultDelayInSecondsByAttemptFuncOne()
{
 return delegate(long attempt)
 {
  Random random = new Random();
  return (int)Math.Round(Math.Pow(attempt - 14.0) + 15.0 + (double)(random.Next(30) * attempt));
 };
}


是不是很了然,就是简单的将委托转换为了匿名方法,但是最终返回的是匿名方法引用,接下来我们再来看第二种方法变体

private static readonly Func<longint> DefaultDelayInSecondsByAttemptFuncTwo = delegate(long attempt)
{
 Random random = new Random();
 return (int)Math.Round(Math.Pow(attempt - 14.0) + 15.0 + (double)(random.Next(30) * attempt));
};

该变体则只是将委托转换为匿名方法后将对应参数传进去,但是最后返回的是委托定义的返回值


好了,本文到此结束,接下来继续我们操作系统的学习,我们下一节再见,来自周末凌晨的晚安。

本文分享自微信公众号 - dotNET跨平台(opendotnet)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!