翼度科技»论坛 编程开发 .net 查看内容

CSharp的lambda表达式匿名类扩展方法

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
c#的lamba表达式

之前已经写过一些关于委托还有事件的文章,今天就来介绍一下lambda表达式。
首先定义需要的函数以及委托
  1. {
  2. public delegate void DoNothingDelegate();
  3. public delegate void StudyDelegate(int id, string name);
  4. private void DoNothing()
  5. {
  6.     Console.WriteLine("DoNothing");
  7. }
  8. private void Study(int id , string name)
  9. {
  10.     Console.WriteLine($"{id} {name} 学习 .Net高级班 " );
  11. }
  12. }
复制代码
在.net farmwork 1.0,会这样写我们的匿名函数
  1.    public void Show()
  2.    {
  3.        {
  4.            //.netframework 1.0的写法
  5.            DoNothingDelegate doNothing = new DoNothingDelegate(DoNothing);
  6.            StudyDelegate study = new StudyDelegate(Study);
  7.        }
  8.    }
复制代码
在.netframework 2.0,会这样写匿名函数, 增加了一个delegate关键字
  1. {
  2.      DoNothingDelegate doNothing = new DoNothingDelegate (delegate ()
  3.      {
  4.          Console.WriteLine("DoNothing");
  5.      });
  6.      StudyDelegate study = new StudyDelegate( delegate (int id, string name)
  7.      {
  8.          Console.WriteLine($"{id} {name} 学习 .Net高级班 ");
  9.      });
  10. }
复制代码
在.netframework3.0,去掉了delegate关键字了,在参数后增加了一个=> goes to
  1. {
  2.     DoNothingDelegate doNothing = new DoNothingDelegate(() =>
  3.     {
  4.         Console.WriteLine("DoNothing");
  5.     });
  6.     StudyDelegate study = new StudyDelegate((int id, string name) =>
  7.     {
  8.         Console.WriteLine($"{id} {name} 学习 .Net高级班 ");
  9.     });
  10. }
复制代码
在.netframework3.0后期,我们可以省略参数的信息
  1. StudyDelegate study = new StudyDelegate((id, name) =>
  2. {
  3.      Console.WriteLine($"{id} {name} 学习 .Net高级班 ");
  4. });
复制代码
如果匿名方法体中只有一行代码,可以省略方法题的大括号
  1. StudyDelegate study = new StudyDelegate((id, name) =>Console.WriteLine($"{id} {name} 学习 .Net高级班 "));
复制代码
只有一个参数的时候,参数的小括号也可以省略掉。
  1. public delegate void StudyNew(int id);
  2. StudyNew study = id => Console.WriteLine($"{id} 学习 .Net高级班 ");
复制代码
如果方法返回值?
如果lambda表达式中只有一行代码,且有返回值,可以省略return,
  1. Func<int> retNum= () => 1;
复制代码
lamba函数的本质是什么?

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

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

有时候,可以需要创建一个临时的类对象,保存数据,方便使用。
一个普通的类对象
  1.   public class Student
  2.   {
  3.       public int Id { get; set; }
  4.       public int ClassId { get; set; }
  5.       public string Name { get; set; }
  6.       public int Age { get; set; }
  7.       public string Description { get; set; }
  8.       public void Study()
  9.       {
  10.           Console.WriteLine($"{this.Id} {this.Name} 跟着老师学习 .Net开发");
  11.       }
  12.       public void StudyQt()
  13.       {
  14.           Console.WriteLine($"{this.Id} {this.Name} 跟着老师学习C++ Qt");
  15.       }
  16.   }
复制代码
当创建一个普通的类对象的时候,这样去创建一个类对象。
  1. Student student = new Student()
  2. {
  3.      Id = 1,
  4.      ClassId = 2,
  5.      Name = "张三",
  6.      Age = 20,
  7.      Description = "这是一个学生"
  8. };
复制代码
现在尝试最原始的方法去创建一个匿名类,
  1. object model = new
  2. {
  3.     Id = 1,
  4.     Name = "小楼一夜听春雨",
  5.     Age = 14,
  6.     Description = "魔刀丁鹏"
  7. };
复制代码
为什么可以定义一个匿名的对象?
因为C#中所有的对象都继承自Object对象.
当尝试使用.去访问其中的属性就会报错.
C#是强类型语言(编译时决定类型),object是在编译时确定类型,因为Object没有Id等属性,所以无法通过.去访问其中的变量.
因此可以使用下面的方法去访问我们的匿名对象中的属性.
  1. dynamic model1 = new
  2. {
  3.      Id = 2,
  4.      Name = "天下第一的剑客",
  5.      Age = 18,
  6.      Description = "神剑山庄谢晓峰"
  7. };
  8. Console.WriteLine(model1.Id);
  9. Console.WriteLine(model1.Age);
  10. Console.WriteLine(model1.Amy); //报错
复制代码
这里使用了dynamic关键字去避开了编译器的检查,会在运行时检查,运行时决定类型.这个出现乱取的问题,导致程序崩溃.
有什么方法可以正确的取出想访问的属性,又可以避免访问不存在的属性那?
var关键字
  1.   var model2 = new
  2.   {
  3.       Id = 3,
  4.       Name = "天下第二的剑客",
  5.       Age = 16,
  6.       Description = "不会剑法的阿飞"
  7.   };
  8.   Console.WriteLine(model2.Id);
  9.   Console.WriteLine(model2.Name);
  10.   //Console.WriteLine(model2.Aniu); //报错!无法访问不存在的变量
复制代码
var类型就是弱类型的变量.
使用的注意事项?

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

  • var配合匿名类型使用
  • var偷懒,配合复杂类型时使用。
  • 在不知道具体什么类型的时候就可以使用var来声明
缺陷
在代码阅读的时候,不是很方便。
建议在大家写代码的时候,尽量明确类型。
扩展方法

为什么需要扩展方法?

  • 扩展:让功能变得更加强大,让不存在功能存在. ---新增逻辑处理
  • 已经存在方法,正常调用,扩展的东西不影响已经存在的方法
  • 如果需求变更,需要支持另外的一个新的功能。
接着上面学生的用例,我们可以追加一些需求.
  1. Student student1 = new Student()
  2. {
  3.     Id = 1,
  4.     ClassId = 2,
  5.     Name = "张三",
  6.     Age = 20,
  7.     Description = "这是一个学生"
  8. };
  9. student1.Study();
  10. student1.StudyQt();
复制代码
如果要增加一个需求--学习嵌入式---直接增加方法.
传统的方式对原有的类进行结构上的修改.
期望:既可以增加新的功能,历史代码不变.直接增加类,在新的类中去完成.
这里就可以使用扩展方法来完成需求.
  1. public static class MethodExtension
  2. {
  3.      public static void StudyEmbedded(this Student student)
  4.      {
  5.          Console.WriteLine($"{student.Id} {student.Name} 跟着老师学习嵌入式开发");
  6.      }
  7. }
复制代码
program.cs
  1. student.StudyEmbedded();
复制代码
可以看到做的操作就是:

  • 把类变成静态类
  • 把方法的第一个参数+this修饰
这样就完成了一个扩展方法.静态方法的调用--可以像实例方法一样去调用.
不用修改原有的任何类中的类,可以新增功能;
有哪些场景?

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

    • 尽可能简化代码
    • 灵活分配,需要就扩展什么.按需扩展,不会有代码冗余.

这里有个问题,我可以给任意类型写扩展方法嘛? 注意:扩展object类型.
[code] public static string SubObj(this object str, int len = 10) {     if (str is null)     {         return string.Empty;     }     if (str.ToString().Length

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具