• C#基础--函数编程


    函数编程

    本章主要讲解 C#7的新特性,比如本地函数、元组和模式匹配

    本地函数

    本地函数在方法的作用域、属性访问器、构造函 数或者lambda表达式内声明。本地函数只能在包含成员的作用域内调用。可以使用本地函数,而不是使用仅一 个地方需要的私有方法。

    private static void IntroWithLambdaExpression()
    {
        Func<int, int, int> add = (x, y) =>
        {
            return x + y;
        };
        int result = add(37, 5);
        Console.WriteLine(result);
    }
    
    static void IntroWithLocalFunctions()
     {
         int add(int x, int y)
         {
             return x + y;
         }
         int result = add(37, 5);
         Console.WriteLine(result);
     }
    
     private static void IntroWithLocalFunctionsWithExpressionBodies()
     {
         int add(int x, int y) => x + y;
    
         int result = add(37, 5);
         Console.WriteLine(result);
     }
    
     private static void IntroWithLocalFunctionsWithClosures()
     {
         int z = 3;
         int result = add(37, 5);
         Console.WriteLine(result);
    
         int add(int x, int y) => x + y + z;
     }
    

    递归本地函数

    另一个使用本地函数的场景是递归调用,如下面使用Quicksort方法的示例所示。这里,本地函数Sort是
    递归调用的,直到集合排好序为止

    public static void QuickSort<T>(T[] elements) where T : IComparable<T>
    {
        void Sort(int start, int end)
        {
            int i = start, j = end;
            var pivot = elements[(start + end) / 2];
    
            while (i <= j)
            {
                while (elements[i].CompareTo(pivot) < 0) i++;
                while (elements[j].CompareTo(pivot) > 0) j--;
                if (i <= j)
                {
                    T tmp = elements[i];
                    elements[i] = elements[j];
                    elements[j] = tmp;
                    i++;
                    j--;
                }
            }
            if (start < j) Sort(start, j);
            if (i < end) Sort(i, end);
        }
    
        Sort(0, elements.Length - 1);
    }
    

    元组

    元组能够组合不同类型的对象。使用数组可以组合相同类型的对象,而元组允许使用类型的不同组合。元 组有助于减少以下两个需求:

    • 定义自定义类或结构,以返回多个值
    • 定义参数,从方法中返回多个值

    元组的声明和初始化

    可以使用圆括号声明一个元组,并使用通过括号创建的元组字面量来初始化。

    private static void IntroTuples()
    {
        (string s, int i, Person p) t = ("magic", 42, new Person("Matthias", "Nagel"));
        Console.WriteLine($"s: {t.s}, i: {t.i}, p: {t.p}");
    
        var t2 = ("magic", 42, new Person("Matthias", "Nagel"));
        Console.WriteLine($"string: {t2.Item1}, int: {t2.Item2}, person: {t2.Item3}");
    
        var t3 = (s: "magic", i: 42, p: new Person("Matthias", "Nagel"));
        Console.WriteLine($"s: {t3.s}, i: {t3.i}, p: {t3.p}");
    
        (string astring, int anumber, Person aperson) t4 = t3;
        Console.WriteLine($"s: {t4.astring}, i: {t4.anumber}, p: {t4.aperson}");
    }
    

    元组解构

    还可以将元组分解为变量。为此,只需要从前面的代码示例中删除元组变量,并在括号中定义变量名。然 后可以直接访问变量,其中包含元组部分的值

    private static void TupleDeconstruction()
    {
        (string s, int i, Person p) = ("magic", 42, new Person("Stephanie", "Nagel"));
        Console.WriteLine($"s: {s}, i: {i}, p: {p}");
        (var s1, var i1, var p1) = ("magic", 42, new Person("Stephanie", "Nagel"));
        Console.WriteLine($"s: {s1}, i: {i1}, p: {p1}");
    
        string s2;
        int i2;
        Person p2;
        (s2, i2, p2) = ("magic", 42, new Person("Katharina", "Nagel"));
        Console.WriteLine($"s: {s2}, i: {i2}, p: {p2}");
    
        (string s3, _, _) = ("magic", 42, new Person("Katharina", "Nagel"));
        Console.WriteLine(s3);
    }
    

    元组的返回

    static (int result, int remainder) Divide(int dividend, int divisor)
    {
        int result = dividend / divisor;
        int remainder = dividend % divisor;
        return (result, remainder);
    }
    

    模式匹配

    从面向对象的观点来看,最好总是使用具体的类型和接口来解决问题。然而,通常这并不容易做到。在数 据库中,查询可能会给出与任何层次结构都无关的不同对象类型。访问API服务时,可以返回一个列表或对象, 或者可能什么也不返回。因此,方法通常应该与不同的类型一起工作。这就是模式匹配可以提供帮助的地方。

    模式匹配与is运算符

    与is运算符的简单匹配是const模式。在这个模式中,可以将对象与常量值进行比较

    static void IsOperator(object item)
    {
        // const pattern
        if (item is null)
        {
            Console.WriteLine("item is null");
        }
    
        if (item is 42)
        {
            Console.WriteLine("item is 42");
        }
    
        // type pattern
        if (item is int)
        {
            Console.WriteLine($"Item is of type int");
        }
    
        if (item is int i)
        {
            Console.WriteLine($"Item is of type int with a value {i}");
        }
    
        if (item is string s)
        {
            Console.WriteLine($"Item is a string: {s}");
        }
    
        if (item is Person p && p.FirstName.StartsWith("Ka"))
        {
            Console.WriteLine($"Item is a person: {p.FirstName} {p.LastName}");
        }
    
        if (item is IEnumerable<Person> people)
        {
            string names = string.Join(", ", people.Select(p1 => p1.FirstName).ToArray());
            Console.WriteLine($"it's a Person collection containing {names}");
        }
    
        // var pattern
        if (item is var every)
        {
            Console.WriteLine($"it's var of type {every?.GetType().Name ?? "null"} with the value {every ?? "nothing"}");
        }
    }
    

    模式匹配与switch语句

    对于switch语句,也可以使用三种模式类型。

    static void SwitchStatement(object item)
    {
        switch (item)
        {
            case null:
            case 42:
                Console.WriteLine("it's a const pattern");
                break;
            case int i:
                Console.WriteLine($"it's a type pattern with int: {i}");
                break;
            case string s:
                Console.WriteLine($"it's a type pattern with string: {s}");
                break;
            case Person p when p.FirstName == "Katharina":
                Console.WriteLine($"type pattern match with Person and when clause: {p}");
                break;
            case Person p:
                Console.WriteLine($"type pattern match with Person: {p}");
                break;
            case var every:
                Console.WriteLine($"var pattern match: {every?.GetType().Name}");
                break;
            default:
        }
    }
    

    模式匹配与泛型

    如果需要与泛型相匹配的模式,则需要将编译器配置为至少C# 7.1 C# 7.1为泛型添加了模式匹配。

    public class HealthPackage
    {
        public void CheckHealth()
        {
        }
    }
    public class HttpManager
    {
        public void Send<T>(T package)
        {
            if (package is HealthPackage hp)
            {
                hp.CheckHealth();
            }
            //...
        }
    }
    
  • 相关阅读:
    黑豹程序员-知识点-写一个bat一次执行多条命令
    YBTOJ 树形dp合集
    Vue3待办列表-日记与便签-LOL英雄资料-课程大作业
    Perl语言入门:探索Perl语法规则的基本特点
    四书五经 中庸
    如何在 Vue 3 中使用 Ant Design
    WebRTC音视频通话-WebRTC推拉流过程中日志log输出
    0.8秒一张图40hx矿卡stable diffusion webui 高质极速出图组合(24.3.3)
    算法练习——柱状图中最大的矩形 leetcode.80 python
    关于ASP.NET Core WebSocket实现集群的思考
  • 原文地址:https://blog.csdn.net/huan13479195089/article/details/127044311