cari
Rumahpembangunan bahagian belakangTutorial C#.Net详细介绍C#函数式编程的示例代码

  提起函数式编程,大家一定想到的是语法高度灵活和动态的LISP,Haskell这样古老的函数式语言,往近了说ruby,javascript,F#也是函数式编程的流行语言。然而自从.net支持了lambda表达式,C#虽然作为一种指令式程序设计语言,在函数式编程方面也毫不逊色。我们在使用c#编写代码的过程中,有意无意的都会使用高阶函数,组合函数,纯函数缓存等思想,连表达式树这样的idea也来自函数式编程思想。所以接下来我们把常用的函数式编程场景做个总结,有利于我们在程序设计过程中灵活应用这些技术,拓展我们的设计思路和提高代码质量。

  一、高阶函数

  高阶函数通俗的来讲:某个函数中使用了函数作为参数,这样的函数就称为高阶函数。根据这样的定义,.net中大量使用的LINQ表达式,Where,Select,SelectMany,First等方法都属于高阶函数,那么我们在自己写代码的时候什么时候会用到这种设计?

  举例:设计一个计算物业费的函数,var fee=square*price, 而面积(square)根据物业性质的不同,计算方式也不同。民用住宅,商业住宅等需要乘以不同的系数,根据这样的需求我们试着设计下面的函数:

  民用住宅面积:

public Func<int,int,decimal> SquareForCivil()
{
    return (width,hight)=>width*hight;
}

  商业住宅面积:

public Func<int, int, decimal> SquareForBusiness()
{
    return (width, hight) => width * hight*1.2m;
}

  这些函数都有共同的签名:Func31803993a3bae4f7d54758d225c3e107,所以我们可以利用这个函数签名设计出计算物业费的函数:

public decimal PropertyFee(decimal price,int width,int hight, Func<int, int, decimal> square)
{
    return price*square(width, hight);
}

  是不是很easy,写个测试看看

[Test]
public void Should_calculate_propertyFee_for_two_area()
{
    //Arrange
    var calculator = new PropertyFeeCalculator();
    //Act
    var feeForBusiness= calculator.PropertyFee(2m,2, 2, calculator.SquareForBusiness());
    var feeForCivil = calculator.PropertyFee(1m, 2, 2, calculator.SquareForCivil());
    //Assert
    feeForBusiness.Should().Be(9.6m);
    feeForCivil.Should().Be(4m);
}

  二、惰性求值

  C#在执行过程使用严格求值策略,所谓严格求值是指参数在传递给函数之前求值。这个解释是不是还是有点不够清楚?我们看个场景:有一个任务需要执行,要求当前内存使用率小于80%,并且上一步计算的结果46c3f0744c8dff3b1bcb61e3393fa07f类,大家可以在有这种需求的场景下使用这个机制。

  三、函数柯里化(Curry)

  柯里化也称作局部套用。定义:是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术,ps:为什么官方解释这么绕口?

  看到这样的定义估计大家也很难明白这是这么一回事,所以我们从curry的原理讲起:

  写一个两个数相加的函数:

public Func<int, int, int> AddTwoNumber()
{
    return (x, y) => x + y;
}

  ok, 如何使用这个函数?

var result= _curringReasoning.AddTwoNumber()(1,2);

  1+2=3,调用很简单。需求升级,我们需要一个函数,这个函数要求输入一个参数(number),算出10+输入的参数(number)的结果。估计有人要说了,这需求上面的代码完全可以实现啊,第一个参数你传入10不就完了么,ok,如果你是这样想的,我也是无可奈何。还有人可能说了,再写一个重载,只要一个参数即可,实际情况是不容许,我们在调用别人提供的api,无法添加重载。可以看到局部套用的使用场景不是一种很普遍的场景,所以在合适的场景配合合适的技术才是最好的设计,我们来看局部套用的实现:

public Func<int, Func<int, int>> AddTwoNumberCurrying()
{
    Func<int, Func<int, int>> addCurrying = x => y => x + y;
    return addCurrying;
}

  表达式x => y => x + y得到的函数签名为Func9d41917661ce24c26c6c064bdf051b81>,这个函数签名非常清楚,接收一个int类型的参数,得到一个Func6721ea9c2f3961346cef19f5e7477758类型的函数。此时如果我们再调用:

//Act
var curringResult = curringReasoning.AddTwoNumberCurrying()(10);
var result = curringResult(2);
 
//Assert
result.Should().Be(12);

  这句话:var curringResult = curringReasoning.AddTwoNumberCurrying()(10); 生成的函数就是只接收一个参数(number),且可以计算出10+number的函数。

  同样的道理,三个数相加的函数:

public Func<int,int,int,int> AddThreeNumber()
{
    return (x, y, z) => x + y + z;
}

  局部套用版本:

public Func<int,Func<int,Func<int,int>>> AddThreeNumberCurrying()
{
    Func<int, Func<int, Func<int, int>>> addCurring = x => y => z => x + y + z;
    return addCurring;
}

  调用过程:

[Test]
public void Three_number_add_test()
{
    //Arrange
    var curringReasoning = new CurryingReasoning();
 
    //Act
    var result1 = curringReasoning.AddThreeNumber()(1, 2, 3);
    var curringResult = curringReasoning.AddThreeNumberCurrying()(1);
    var curringResult2 = curringResult(2);
    var result2 = curringResult2(3);
    
    //Assert
    result1.Should().Be(6);
    result2.Should().Be(6);
}

  当函数参数多了之后,手动局部套用越来越不容易写,我们可以利用扩展方法自动局部套用:

public static Func<T1, Func<T2, TResult>> Curry<T1, T2, TResult>(this Func<T1, T2, TResult> func)
{
    return x => y => func(x, y);
}
 
public static Func<T1, Func<T2, Func<T3, TResult>>> Curry<T1, T2, T3, TResult>(this Func<T1, T2, T3,TResult> func)
{
    return x => y => z=>func(x, y,z);
}

  同样的道理,Actiona8093152e673feb7aba1828c43532094签名的函数也可以自动套用

  有了这些扩展方法,使用局部套用的时候就更加easy了

[Test]
public void Should_auto_curry_two_number_add_function()
{
    //Arrange
    var add = _curringReasoning.AddTwoNumber();
    var addCurrying = add.Curry();
 
    //Act
    var result = addCurrying(1)(2);
 
    //Assert
    result.Should().Be(3);
}

  好了,局部套用就说到这里,stackoverflow有几篇关于currying使用的场景和定义的文章,大家可以继续了解。

  函数式编程还有一些重要的思想,例如:纯函数的缓存,所为纯函数是指函数的调用不受外界的影响,相同的参数调用得到的值始终是相同的。尾递归,单子,代码即数据(.net中的表达式树),部分应用,组合函数,这些思想有的我也仍然在学习中,有的还在思考其最佳使用场景,所以不再总结,如果哪天领会了其思想会补充。

  四、设计案例

  最后我还是想设计一个场景,把高阶函数,lambda表达式,泛型方法结合在一起,我之所以设计这样的例子是因为现在很多的框架,开源的项目都有类似的写法,也正是因为各种技术和思想结合在一起,才有了极富有表达力并且非常优雅的代码。

  需求:设计一个单词查找器,该查找器可以查找某个传入的model的某些字段是否包含某个单词,由于不同的model具有不同的字段,所以该查找需要配置,并且可以充分利用vs的智能提示。

  这个功能其实就两个方法:

private readonly List<Func<string, bool>> _conditions; 
 
public WordFinder<TModel> Find<TProperty>(Func<TModel,TProperty> expression)
{
    Func<string, bool> searchCondition = word => expression(_model).ToString().Split(&#39; &#39;).Contains(word);
    _conditions.Add(searchCondition);
    return this;
}
 
public bool Execute(string wordList)
{
    return _conditions.Any(x=>x(wordList));
}

  使用:

[Test]
public void Should_find_a_word()
{
    //Arrange
    var article = new Article()
    {
        Title = "this is a title",
        Content = "this is content",
        Comment = "this is comment",
        Author = "this is author"
    };
 
    //Act
    var result = Finder.For(article)
        .Find(x => x.Title)
        .Find(x => x.Content)
        .Find(x => x.Comment)
        .Find(x => x.Author)
        .Execute( "content");
 
    //Assert
    result.Should().Be(true);
}

  该案例本身不具有实用性,但是大家可以看到,正是各种技术的综合应用才设计出极具语义的api, 如果函数参数改为Expression7e21a607b5f8b4a44e84d6cad53bd045> 类型,我们还可以读取到具体的属性名称等信息。

Atas ialah kandungan terperinci 详细介绍C#函数式编程的示例代码. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Masa Depan C# .NET: Trend dan PeluangMasa Depan C# .NET: Trend dan PeluangApr 29, 2025 am 12:02 AM

Trend masa depan C#.NET terutamanya tertumpu pada tiga aspek: pengkomputeran awan, microservices, AI dan integrasi pembelajaran mesin, dan pembangunan silang platform. 1) Pengkomputeran awan dan microservices: C#.NET mengoptimumkan prestasi persekitaran awan melalui platform Azure dan menyokong pembinaan seni bina microservice yang cekap. 2) Integrasi AI dan Pembelajaran Mesin: Dengan bantuan Perpustakaan ML.NET, pemaju C# boleh membenamkan model pembelajaran mesin dalam aplikasi mereka untuk mempromosikan pembangunan aplikasi pintar. 3) Pembangunan silang platform: Melalui .Netcore dan .NET5, C# Aplikasi boleh dijalankan pada Windows, Linux dan MacOS, memperluaskan skop penempatan.

C# .NET Pembangunan Hari Ini: Trend dan Amalan TerbaikC# .NET Pembangunan Hari Ini: Trend dan Amalan TerbaikApr 28, 2025 am 12:25 AM

Perkembangan terkini dan amalan terbaik dalam pembangunan C#. NET termasuk: 1. Pengaturcaraan Asynchronous meningkatkan respons aplikasi, dan memudahkan kod yang tidak menyekat menggunakan async dan menunggu kata kunci; 2. LINQ menyediakan fungsi pertanyaan yang kuat, memanipulasi data dengan cekap melalui pelaksanaan dan pokok ekspresi yang tertunda; 3. Cadangan Pengoptimuman Prestasi termasuk menggunakan pengaturcaraan asynchronous, mengoptimumkan pertanyaan LINQ, memori pengurusan rasional, meningkatkan kebolehbacaan dan penyelenggaraan kod, dan ujian unit penulisan.

C# .NET: Membina aplikasi dengan ekosistem .NETC# .NET: Membina aplikasi dengan ekosistem .NETApr 27, 2025 am 12:12 AM

Bagaimana Membina Aplikasi Menggunakan .NET? Membina aplikasi menggunakan .NET boleh dicapai melalui langkah-langkah berikut: 1) Memahami asas-asas .NET, termasuk C# bahasa dan sokongan pembangunan silang platform; 2) mempelajari konsep teras seperti komponen dan prinsip kerja ekosistem .NET; 3) menguasai penggunaan asas dan lanjutan, dari aplikasi konsol mudah ke operasi WebAPIS dan pangkalan data yang kompleks; 4) terbiasa dengan kesilapan biasa dan teknik debugging, seperti konfigurasi dan isu sambungan pangkalan data; 5) Pengoptimuman prestasi aplikasi dan amalan terbaik, seperti pengaturcaraan dan caching asynchronous.

C# sebagai bahasa yang serba boleh. NET: Aplikasi dan contohC# sebagai bahasa yang serba boleh. NET: Aplikasi dan contohApr 26, 2025 am 12:26 AM

C# digunakan secara meluas dalam aplikasi peringkat perusahaan, pembangunan permainan, aplikasi mudah alih dan pembangunan web. 1) Dalam aplikasi peringkat perusahaan, C# sering digunakan untuk ASP.Netcore untuk membangunkan WebAPI. 2) Dalam pembangunan permainan, C# digabungkan dengan enjin Perpaduan untuk merealisasikan kawalan peranan dan fungsi lain. 3) C# menyokong polimorfisme dan pengaturcaraan tak segerak untuk meningkatkan fleksibiliti kod dan prestasi aplikasi.

C# .net untuk pembangunan web, desktop, dan mudah alihC# .net untuk pembangunan web, desktop, dan mudah alihApr 25, 2025 am 12:01 AM

C# dan .NET sesuai untuk pembangunan web, desktop dan mudah alih. 1) Dalam pembangunan web, ASP.Netcore menyokong pembangunan silang platform. 2) Pembangunan desktop menggunakan WPF dan WinForms, yang sesuai untuk keperluan yang berbeza. 3) Pembangunan mudah alih menyedari aplikasi silang platform melalui Xamarin.

C# .NET Ecosystem: Rangka Kerja, Perpustakaan, dan AlatC# .NET Ecosystem: Rangka Kerja, Perpustakaan, dan AlatApr 24, 2025 am 12:02 AM

Ekosistem C#.NET menyediakan rangka kerja dan perpustakaan yang kaya untuk membantu pemaju membina aplikasi dengan cekap. 1.asp.NetCore digunakan untuk membina aplikasi web berprestasi tinggi, 2.EntityFrameworkCore digunakan untuk operasi pangkalan data. Dengan memahami penggunaan dan amalan terbaik alat -alat ini, pemaju dapat meningkatkan kualiti dan prestasi aplikasi mereka.

Menggunakan C# .NET Aplikasi ke Azure/AWS: Panduan Langkah demi LangkahMenggunakan C# .NET Aplikasi ke Azure/AWS: Panduan Langkah demi LangkahApr 23, 2025 am 12:06 AM

Bagaimana cara menggunakan aplikasi C# .net ke Azure atau AWS? Jawapannya ialah menggunakan Azureappservice dan AwselasticBeansTalk. 1. Pada Azure, mengautomasikan penggunaan menggunakan Azureappservice dan Azurepipelines. 2. Pada AWS, gunakan Amazon ElasticBeansTalk dan AWSLambda untuk melaksanakan penempatan dan pengiraan tanpa pelayan.

C# .NET: Pengenalan kepada bahasa pengaturcaraan yang kuatC# .NET: Pengenalan kepada bahasa pengaturcaraan yang kuatApr 22, 2025 am 12:04 AM

Gabungan C# dan .NET menyediakan pemaju dengan persekitaran pengaturcaraan yang kuat. 1) C# menyokong polimorfisme dan pengaturcaraan asynchronous, 2) .NET menyediakan keupayaan silang platform dan mekanisme pemprosesan serentak, yang menjadikannya digunakan secara meluas dalam pembangunan aplikasi desktop, web dan mudah alih.

See all articles

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Alat panas

VSCode Windows 64-bit Muat Turun

VSCode Windows 64-bit Muat Turun

Editor IDE percuma dan berkuasa yang dilancarkan oleh Microsoft

SublimeText3 versi Inggeris

SublimeText3 versi Inggeris

Disyorkan: Versi Win, menyokong gesaan kod!

DVWA

DVWA

Damn Vulnerable Web App (DVWA) ialah aplikasi web PHP/MySQL yang sangat terdedah. Matlamat utamanya adalah untuk menjadi bantuan bagi profesional keselamatan untuk menguji kemahiran dan alatan mereka dalam persekitaran undang-undang, untuk membantu pembangun web lebih memahami proses mengamankan aplikasi web, dan untuk membantu guru/pelajar mengajar/belajar dalam persekitaran bilik darjah Aplikasi web keselamatan. Matlamat DVWA adalah untuk mempraktikkan beberapa kelemahan web yang paling biasa melalui antara muka yang mudah dan mudah, dengan pelbagai tahap kesukaran. Sila ambil perhatian bahawa perisian ini

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

SecLists

SecLists

SecLists ialah rakan penguji keselamatan muktamad. Ia ialah koleksi pelbagai jenis senarai yang kerap digunakan semasa penilaian keselamatan, semuanya di satu tempat. SecLists membantu menjadikan ujian keselamatan lebih cekap dan produktif dengan menyediakan semua senarai yang mungkin diperlukan oleh penguji keselamatan dengan mudah. Jenis senarai termasuk nama pengguna, kata laluan, URL, muatan kabur, corak data sensitif, cangkerang web dan banyak lagi. Penguji hanya boleh menarik repositori ini ke mesin ujian baharu dan dia akan mempunyai akses kepada setiap jenis senarai yang dia perlukan.