首页 > 其他分享 >CSharp的lambda表达式匿名类扩展方法

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

时间:2024-03-14 16:22:40浏览次数:22  
标签:Console id 匿名 WriteLine CSharp new Id public lambda

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进行反编译来看一下匿名方法的实现是怎么样的

img

本质上来说,其实就是一个方法--匿名方法, 在类里面会生成和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,也不是很建议大家去泛型扩展.

标签:Console,id,匿名,WriteLine,CSharp,new,Id,public,lambda
From: https://www.cnblogs.com/wenlong-4613615/p/18071142

相关文章

  • Lambda表达式
    使用Lambda表达式进行集合遍历❌未使用Lambda表达式:Listlist=Arrays.asList("apple","banana","orange");for(Stringfruit:list){System.out.println(fruit);}✅使用Lambda表达式:Listlist=Arrays.asList("apple","banana&q......
  • lambda表达式
    本文章将简要介绍java中lambda的基本知识和使用一.lambda的构成lambda表达式的语法结构相对简单,主要由以下几个部分组成:lambda关键字: lambda关键字用于标识这是一个lambda表达式,表示即将定义一个匿名函数。参数列表: 参数列表即用括号括起来的形式参数,可以包含零个或多个......
  • 07-Lambda表达式
    泛型泛型(Generics)是JDK1.5版本增加的技术,他可以帮助我们建立类型安全的集合。在使用了泛型的集合中,不必进行强制类型转换。JDK提供了支持泛型的编译器,将运行时的类型检查提前到了编译时执行,使代码可读性和安全性更高。不使用泛型:publicstaticvoidmain(String[]args){......
  • java8特性-lambda表达式
    Lambda表达式的使用1.举例:(o1,o2)->Integer.compare(o1,o2);格式:->:lambda操作符或箭头操作符->左边:lambda形参列表(其实就是接口中的抽象方法的形参列表)->右边:labbda体(其实就是重写抽象方法中的方法体)3.lambda表达式的使用:(分为六种情况)方式一:无参,无返回值......
  • Java8方法引用简化Lambda
    静态方法引用importlombok.AllArgsConstructor;importlombok.Data;importjava.lang.reflect.Array;importjava.util.Arrays;importjava.util.Comparator;importjava.util.zip.DeflaterOutputStream;/***@authorPickle*@versionV1.0*@date2024/3/823:3......
  • c++ lambda表达式
    引入lambda表达式也有人称之为匿名函数,能够在任何作用域下快速定义一个函数下面这行代码就是一个最简单的lambda表达式,最后输出为3autof=[](intx,inty)->int{returnx+y;};cout<<f(1,2);我们来解析一下lambda表达式autof=[](intx,inty)->int{returnx+y;};......
  • C#中的delegate与Lambda表达式
    参考:Lambda表达式和匿名函数 什么是lambda表达式?C#中的lambda表达式是一种匿名函数,可以用于简化代码,避免定义命名函数或委托。lambda表达式的语法如下:(parameter1,parameter2,...)=>expressionlambda表达式的示例:C#//将一个数字加1Func<int,int>addO......
  • C#lambda与Linq区别
    相同点:都是用于查询和筛选数据的工具。异同点:**1.语法不同:Lambda是一种匿名函数,用于创建委托和表达式树;而Linq是一种查询语句,它使用特定的关键字和语法来查询数据。**2.功能不同:Lambda表达式可用于任何需要委托或表达式树的场合,而Linq语句只能用于查询和筛选数据。**3......
  • Lambda表达式
    功能接口的传递在JDK8之前,函数参数的功能性接口往往用匿名内部类的形式实现,但是JDK8更新了Lambda表达式的新特性,简化了匿名内部类。Java8的一个大亮点是引入Lambda表达式,使用它设计的代码会更加简洁。当开发者在编写Lambda表达式时,也会随之被编译成一个函数式接口。lambda表......
  • lambda(持续补充)
    1lambda的捕获列表类似于bind的参数绑定:将定义lambda定义处的绑定的变量值作为该lambda的固定参数。e.gvoidcallfunction(){intdd=100;intee=200;autolam=[dd,ee](intparam1)->int{returndd+ee+param1;};------11处在定义lambda的地方dd,ee就给定了是100,20......