C#.委托赋值表达式,​匿名方法与Lambda

var code = "0cd70012-a008-42f0-a18d-1bce9d8ac0e7"

委托

委托是一种特殊的引用类型, 所以使用委托类似于使用一个类, 需要先声明, 然后再调用. 与一般类的声明又有所不同, 不使用classnew关键字, 而是使用专门的delegate. 是否与 py 和 js 一样可以直接将方法赋给一个变量然后调用呢? 不可以, 编译器会报错, 尚不知如何声明一个方法组对象变量. 在思考委托时, 不能仅仅把委托对象当作一个方法的别名, 他就是一个委托类的实例, 就是委托对象, 以笔者的知识储备来看, 它是一个全新的数据结构, 有他自己的特性. 使用委托一般是三个步骤: 声明委托类, 创建委托对象, 绑定方法.

delegate void CalcuAndPrint(int a, int b);
// 声明一个委托类, 可以看见括号前面是绿色的, 是类名的高亮

class Program
{
    static void SumAndPrint(int a, int b)
    {
        Console.WriteLine(a + b);
    }
    static void SubAndPrint(int a, int b)
    {
        Console.WriteLine(a - b);
    }
    static CalcuAndPrint GiveMeTwoFunc()
    {
        CalcuAndPrint func = SumAndPrint;
        return func += SubAndPrint;
    }
    static void Main()
    {
        CalcuAndPrint func;
        // 委托类不是静态类, 使用需要实例化
        func = SumAndPrint;
        // 为委托对象赋值, 值是一个方法
        func(1,1); // 如同函数一样调用委托对象
        // void func2 = SumAndPrint;
        // 错误 CS0029 无法将类型“方法组”隐式转换为“void”
        // 错误 CS1547 关键字 "void" 不能在此上下文中使用
        func += SubAndPrint;
        // func += (CalcuAndPrint)SubAndPrint; // 显式转换, 可行.
        // 本质是"方法组"向"委托"的隐式转换
        // var func0 = SumAndPrint;
        // 错误 CS8400 功能“推断的委托类型”在 C# 8.0 中不可用。请使用语言版本 10.0 或更高版本。
        // func += new CalcuAndPrint(Program.SubAndPrint); // 完整写法
        func(9,6);
        GiveMeTwoFunc()(6,9);
        // 委托对象直接通过方法的返回值返回. 
        // 可以直接调用这个委托类, 不用重新声明变量赋值再调用委托对象
    }
}

委托赋值表达式

简写形式可以用var关键字简化吗? 虽然说方法作为参数传递需要先封装成委托, 但可以直接传递吗? 不可使用var, .net core 3.1 使用的 8.0 版本的 C#, 功能“推断的委托类型”在 C# 8.0 中不可用. 请使用语言版本 10.0 或更高版本. 第二个问题如之前的问题一样, 方法的类型名为方法组, 参数传递时需要声明类型, 方法组目前尚不可知, 不能绕过委托直接传递. 所谓的委托赋值表达式的简写形式, 其实是方法组类型对象向委托类型对象类型的隐式转换.

匿名方法与Lambda

public class Stu
{
  static private int _id = 1120000;
  private string name;
  public string Name {get { return name; } }
  private int id;
  private int age;
  public int Age { get { return age; } }
  private int avgScore;
  public int Score { 
      get { return avgScore; }
      set { avgScore = value; }
  }
  public Stu(string name, int age, int score)
  {
      id = _id;
      _id++;
      this.age = age;
      avgScore = score;
      this.name = name;
  }
  public delegate Stu StuCompareMethod(Stu stu1, Stu stu2);
  public override string ToString()
  {
      return $"{id}:{name} {age}, {avgScore}";
  }
  public static void SortAndPrint(Stu[] Stus, StuCompareMethod method)
  {
      Stu temp;
      for (int i = 0; i < Stus.Length; i++)
      {
          for (int j = Stus.Length - 1 ; j > i; j--)
          {
              if (method(Stus[j],Stus[j-1]) != Stus[j])
              {
                  temp = Stus[j];
                  Stus[j] = Stus[j-1];
                  Stus[j-1] = temp;                       
              }
          }
      }
      foreach (Stu stu in Stus)
      {
          Console.WriteLine(stu);
      }
  }
}

internal class Program
{
  static void Main(string[] args)
  {
      Stu stu0 = new Stu("LongX", 7, 90);
      Stu stu1 = new Stu("DaMo",11,95);
      Stu stu4 = new Stu("U", 60, 100);
      Stu stu2 = new Stu("Emotion", 15, 85);
      Stu stu3 = new Stu("Jayden", 19, 87);
      Stu[] Stus = {stu0,stu1,stu4,stu2,stu3};
      Stu.StuCompareMethod SortByAgeDesc = delegate (Stu stu1, Stu stu2)
      {
          if (stu1.Age < stu2.Age)
          {
              return stu1;
          }
          else
          {
              return stu2;
          }
      }; // 按Age降序, 匿名方法描述
      // 匿名方法需要先声明委托对象变量. 这里的匿名是函数没有名字
      // 赋值号前面的变量名不是函数的, 是委托对象的变量名.
      // 匿名方法描述直接在赋值号后使用 delegate 关键字
      // 紧随其后定义参数和方法体, 直接完成了委托绑定
      Stu.SortAndPrint(Stus, SortByAgeDesc);
      Console.WriteLine("");
      // 按Score升序, Lambda 表达式描述
      // (参数类型 参数名) => { return 返回值;}
      // 最简方式: (参数名) => 返回值
      // 使用 Lambda 表达式不需要额外绑定委托
      // 在参数传递时, Lambda 表达式将自动从方法组隐式转化为委托
      Stu.SortAndPrint(Stus, (stu1, stu2) => (stu1.Score > stu2.Score) ? stu1 : stu2);
  }
}

委托加减运算

连续输出是什么意思? 顺序又是怎样? 按照目前的例子来看, 是按照绑定是的顺序进行的连续输出.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值