c#的lamba表达式

之前已经写过一些关于委托还有事件的文章,今天就来介绍一下lambda表达式。

首先定义需要的函数以及委托

{
public delegate void DoNothingDelegate();
public delegate void StudyDelegate(int id, string name); private void DoNothing()
{
Console.WriteLine("DoNothing");
} private void Study(int id , string name)
{
Console.WriteLine($"{id} {name} 学习 .Net高级班 " );
}
}

在.net farmwork 1.0,会这样写我们的匿名函数


public void Show()
{
{
//.netframework 1.0的写法
DoNothingDelegate doNothing = new DoNothingDelegate(DoNothing);
StudyDelegate study = new StudyDelegate(Study);
}
}

在.netframework 2.0,会这样写匿名函数, 增加了一个delegate关键字

 {
DoNothingDelegate doNothing = new DoNothingDelegate (delegate ()
{
Console.WriteLine("DoNothing");
});
StudyDelegate study = new StudyDelegate( delegate (int id, string name)
{
Console.WriteLine($"{id} {name} 学习 .Net高级班 ");
});
}

在.netframework3.0,去掉了delegate关键字了,在参数后增加了一个=> goes to

{
DoNothingDelegate doNothing = new DoNothingDelegate(() =>
{
Console.WriteLine("DoNothing");
});
StudyDelegate study = new StudyDelegate((int id, string name) =>
{
Console.WriteLine($"{id} {name} 学习 .Net高级班 ");
});
}

在.netframework3.0后期,我们可以省略参数的信息

 StudyDelegate study = new StudyDelegate((id, name) =>
{
Console.WriteLine($"{id} {name} 学习 .Net高级班 ");
});

如果匿名方法体中只有一行代码,可以省略方法题的大括号

StudyDelegate study = new StudyDelegate((id, name) =>Console.WriteLine($"{id} {name} 学习 .Net高级班 "));

只有一个参数的时候,参数的小括号也可以省略掉。

public delegate void StudyNew(int id);
StudyNew study = id => Console.WriteLine($"{id} 学习 .Net高级班 ");

如果方法返回值?

如果lambda表达式中只有一行代码,且有返回值,可以省略return,

Func<int> retNum= () => 1;

lamba函数的本质是什么?

这里使用ilspy进行反编译来看一下匿名方法的实现是怎么样的

本质上来说,其实就是一个方法--匿名方法, 在类里面会生成和lambad 表达式参数和返回值完全匹配的方法.

匿名类

有时候,可以需要创建一个临时的类对象,保存数据,方便使用。

一个普通的类对象


public class Student
{
public int Id { get; set; }
public int ClassId { get; set; } public string Name { get; set; } public int Age { get; set; } public string Description { get; set; } public void Study()
{
Console.WriteLine($"{this.Id} {this.Name} 跟着老师学习 .Net开发"); } public void StudyQt()
{
Console.WriteLine($"{this.Id} {this.Name} 跟着老师学习C++ Qt");
}
}

当创建一个普通的类对象的时候,这样去创建一个类对象。

 Student student = new Student()
{
Id = 1,
ClassId = 2,
Name = "张三",
Age = 20,
Description = "这是一个学生"
};

现在尝试最原始的方法去创建一个匿名类,

object model = new
{
Id = 1,
Name = "小楼一夜听春雨",
Age = 14,
Description = "魔刀丁鹏"
};

为什么可以定义一个匿名的对象?

因为C#中所有的对象都继承自Object对象.

当尝试使用.去访问其中的属性就会报错.

C#是强类型语言(编译时决定类型),object是在编译时确定类型,因为Object没有Id等属性,所以无法通过.去访问其中的变量.

因此可以使用下面的方法去访问我们的匿名对象中的属性.

 dynamic model1 = new
{
Id = 2,
Name = "天下第一的剑客",
Age = 18,
Description = "神剑山庄谢晓峰"
}; Console.WriteLine(model1.Id);
Console.WriteLine(model1.Age);
Console.WriteLine(model1.Amy); //报错

这里使用了dynamic关键字去避开了编译器的检查,会在运行时检查,运行时决定类型.这个出现乱取的问题,导致程序崩溃.

有什么方法可以正确的取出想访问的属性,又可以避免访问不存在的属性那?

var关键字

  var model2 = new
{
Id = 3,
Name = "天下第二的剑客",
Age = 16,
Description = "不会剑法的阿飞"
}; Console.WriteLine(model2.Id);
Console.WriteLine(model2.Name);
//Console.WriteLine(model2.Aniu); //报错!无法访问不存在的变量

var类型就是弱类型的变量.

使用的注意事项?

  1. 不能在匿名类里面声明方法,同时在声明匿名类的属性时候,就给定匿名类的属性初始值.
  2. 不能给属性重新赋值.
  3. var声明的变量必须初始化,必须能推算出类型,也不允许作为方法的参数类型.

使用的建议?

  1. var配合匿名类型使用
  2. var偷懒,配合复杂类型时使用。
  3. 在不知道具体什么类型的时候就可以使用var来声明

缺陷

在代码阅读的时候,不是很方便。

建议在大家写代码的时候,尽量明确类型。

扩展方法

为什么需要扩展方法?

  1. 扩展:让功能变得更加强大,让不存在功能存在. ---新增逻辑处理
  2. 已经存在方法,正常调用,扩展的东西不影响已经存在的方法
  3. 如果需求变更,需要支持另外的一个新的功能。

接着上面学生的用例,我们可以追加一些需求.

Student student1 = new Student()
{
Id = 1,
ClassId = 2,
Name = "张三",
Age = 20,
Description = "这是一个学生"
}; student1.Study();
student1.StudyQt();

如果要增加一个需求--学习嵌入式---直接增加方法.

传统的方式对原有的类进行结构上的修改.

期望:既可以增加新的功能,历史代码不变.直接增加类,在新的类中去完成.

这里就可以使用扩展方法来完成需求.

 public static class MethodExtension
{
public static void StudyEmbedded(this Student student)
{
Console.WriteLine($"{student.Id} {student.Name} 跟着老师学习嵌入式开发");
}
}

program.cs

student.StudyEmbedded();

可以看到做的操作就是:

  1. 把类变成静态类
  2. 把方法的第一个参数+this修饰

这样就完成了一个扩展方法.静态方法的调用--可以像实例方法一样去调用.

不用修改原有的任何类中的类,可以新增功能;

有哪些场景?

  1. 有新的需求来的时候--扩展方法--保证历史代码功能
  2. 要应用第三方的DLL库(提供的功能不完善,我们自己需要升级下----dll,不能修改原有的代码)扩展方法
  3. 封装帮助类库
  4. asp.net core 中,到处都是扩展方法--框架的设计--最小化设计.提供一个最基本、最最最简单的功能,提供给调用方.这种方式在使用的时候,如果想要增强功能,就可以扩展. 好处:
    1. 尽可能简化代码
    2. 灵活分配,需要就扩展什么.按需扩展,不会有代码冗余.

这里有个问题,我可以给任意类型写扩展方法嘛? 注意:扩展object类型.

 public static string SubObj(this object str, int len = 10)
{
if (str is null)
{
return string.Empty;
} if (str.ToString().Length <= 10)
{
return str.ToString();
}
else
{
str = $"{str.ToString().Substring(0, len)}....";
return str.ToString();
} }

program.cs

 object o = "object 类型";
o.SubObj(); int i = 1;
i.SubObj();//可以 string sr = "你好";
sr.SubObj(); str.SubGeneric();
student.SubGeneric(); //隐患

总结:

  1. 扩展的类型具有继承性,扩展父类,所有子类都拥有这个功能;扩展的功能可能不适用一些具体的类型;但是仍然可以调用;可以造成一些类型的功能的污染;----慎用
  2. 不建议扩展object,也不是很建议大家去泛型扩展.

CSharp的lambda表达式匿名类扩展方法的更多相关文章

  1. Lambda表达式匿名类实现接口方法

    Lamb表达式匿名类实现接口方法 import java.util.ArrayList; public class HandlerDemo{ public static void main(Strin ...

  2. java8函数式接口详解、函数接口详解、lambda表达式匿名函数、方法引用使用含义、函数式接口实例、如何定义函数式接口

    函数式接口详细定义 函数式接口只有一个抽象方法 由于default方法有一个实现,所以他们不是抽象的. 如果一个接口定义了一个抽象方法,而他恰好覆盖了Object的public方法,仍旧不算做接口的抽 ...

  3. [二] java8 函数式接口详解 函数接口详解 lambda表达式 匿名函数 方法引用使用含义 函数式接口实例 如何定义函数式接口

    函数式接口详细定义 package java.lang; import java.lang.annotation.*; /** * An informative annotation type use ...

  4. 十二、C# 委托与Lambda表达式(匿名方法的另一种写法)

    委托与Lambda表达式   1.委托概述 2.匿名方法 3.语句Lambda 4.表达式Lambda 5.表达式树   一.委托概述 相当于C++当中的方法指针,在C#中使用delegate 委托来 ...

  5. Lambda表达式&匿名方法

    “Lambda表达式“(lambda Expression)就是一个匿名函数(匿名方法),lambda表达式基于数学中的入演算得名. lambda运算符:所有的lambda表达式都是用新的lambda ...

  6. easyui datagrid remoteSort的实现 Controllers编写动态的Lambda表达式 IQueryable OrderBy扩展

    EF 结合easy-ui datagrid 实现页面端排序 EF动态编写排序Lambda表达式 1.前端页面 var mainListHeight = $(window).height() - 20; ...

  7. EF下lambda与linq查询&&扩展方法

    1. linq查询数据 WebTestDBEntities db = new WebTestDBEntities(); 1.1 linq查询所有列数据 var userInfoList = from ...

  8. java8之lambda表达式(2)-方法引用

    方法引用使用的地方也是在函数式接口,使用方法引用可以使代码更加简单和便捷 在如下代码中 根据List中字符串长度排序的代码可以写成如下: public static void test1_() { L ...

  9. SqlHelper简单实现(通过Expression和反射)5.Lambda表达式解析类

    这个ExpressionHelper类,是整个SqlHelper中,最核心的一个类,主要功能就是将Lambda表达式转换为Sql语句.同时这个转换过程比较复杂,所以下面详细讲解一下思路和这个类的作用. ...

  10. C++使用模板、函数指针、接口和lambda表达式这四种方法做回调函数的区别比较

    在C++中,两个类之间存在一种关系,某个类需要另外一个类去完成某一个功能,完成了之后需要告知该类结果,这种最普通最常见的需求,往往使用回调函数来解决. 如题,我总结下来有这么四种方式可以完成这项功能, ...

随机推荐

  1. Linux-yum卸载软件包

    yum是Linux操作系统中最常用的软件包管理器之一,它可以帮助你很容易地安装.删除和更新软件包.然而,有时候yum在删除软件包时可能会出现一些问题,本文将告诉你如何正确地使用yum卸载软件包,并解决 ...

  2. 在Windows上使用.NET部署到Docker 《让孩子们走出大坑》

    折腾Docker 有几天了,整别的都没这个糟心.目前已经顺利部署运行起来了.顺便给大家分享下处理在Windows上使用.NET部署到Docker的相关问题解决方法. 1.  Docker无法安装问题 ...

  3. NC16645 [NOIP2007]矩阵取数游戏

    题目链接 题目 题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵 ...

  4. NC51216 花店橱窗

    题目链接 题目 题目描述 小q和他的老婆小z最近开了一家花店,他们准备把店里最好看的花都摆在橱窗里. 但是他们有很多花瓶,每个花瓶都具有各自的特点,因此,当各个花瓶中放入不同的花束时,会产生不同的美学 ...

  5. Linux常用的20个命令(上)

    无论你是后端程序员还是前端程序员,都避免不了和Linux打交道.Linux的命令有很多,这里仅介绍常用的20个,方便快速查看,也欢迎大家作补充. 1.mkdir 命令 make directories ...

  6. sensitive word 敏感词(脏词) 如何忽略无意义的字符?达到更好的过滤效果?

    忽略字符 说明 我们的敏感词一般都是比较连续的,比如 傻帽 那就有大聪明发现,可以在中间加一些字符,比如[傻!@#$帽]跳过检测,但是骂人等攻击力不减. 那么,如何应对这些类似的场景呢? 我们可以指定 ...

  7. 【framework】ATMS启动流程

    1 前言 ​ ATMS 即 ActivityTaskManagerService,用于管理 Activity 及其容器(任务.堆栈.显示等).ATMS 在 Android 10 中才出现,由原来的 A ...

  8. Java设计模式-组合模式Composite

    介绍 组合模式(Composite Pattern),又叫部分整体模式,它创建了对象组的树形结构,将对象组合成树状结构以表示"整体-部分"的层次关系. 组合模式依据树形结构来组合对 ...

  9. qt基础知识总结

    qt基础知识总结 1.ctrl+r:快速运行 2.两种模式的区别: 一个是提供菜单栏的,一个不提供菜单栏 3.界面讲解 layouts:布局=水平布局+垂直布局+网格布局+表单布局 spacers:垫 ...

  10. 分层架构设计模式总结-MVC,洋葱架构,整洁架构,六边形架构,DDD等等

    一.单层结构不分层 最开始开发项目时,由于需求较少,用一个单独的工程文件就可以满足开发的需求了,不需要进行划分. 二.MVC 分层和三层 到后面需求越来越多,于是就把文件进行分解,怎么分解?有人提出了 ...