


Detaillierte Einführung in den Beispielcode für die funktionale Programmierung in C#
Wenn man von funktionaler Programmierung spricht, muss jeder an alte funktionale Sprachen wie LISP und Haskell denken, die über eine äußerst flexible und dynamische Syntax verfügen. In jüngerer Zeit sind Ruby, JavaScript und F# auch beliebte Sprachen für funktionale Programmierung. Da .net jedoch Lambda-Ausdrücke unterstützt, ist C# zwar eine zwingende Programmiersprache, steht aber in der funktionalen Programmierung nicht nach. Beim Schreiben von Code in C# werden wir Ideen wie Funktionen höherer Ordnung, kombinierte Funktionen und reines Funktions-Caching absichtlich oder unabsichtlich verwenden. Sogar Ideen wie Ausdrucksbäume stammen aus Ideen der funktionalen Programmierung. Als nächstes werden wir die häufig verwendeten funktionalen Programmierszenarien zusammenfassen, die uns helfen werden, diese Technologien flexibel im Programmierprozess anzuwenden, unsere Designideen zu erweitern und die Codequalität zu verbessern.
1. Funktionen höherer Ordnung
Laienhaft ausgedrückt: Funktionen höherer Ordnung: Eine Funktion, die eine Funktion als Parameter verwendet, wird als Funktion höherer Ordnung bezeichnet. Gemäß dieser Definition sind LINQ-Ausdrücke, Where, Select, SelectMany, First und andere in .net häufig verwendete Methoden allesamt Funktionen höherer Ordnung. Wann werden wir dieses Design verwenden, wenn wir unseren eigenen Code schreiben?
Beispiel: Entwerfen Sie eine Funktion zur Berechnung der Immobiliengebühren, var Gebühr=Quadrat*Preis, und die Fläche (Quadrat) wird je nach Art der Immobilie auf unterschiedliche Weise berechnet. Zivilwohnungen, Gewerbewohnungen usw. müssen mit unterschiedlichen Koeffizienten multipliziert werden. Entsprechend diesen Anforderungen versuchen wir, die folgende Funktion zu entwerfen:
Wohngebiet:
public Func<int,int,decimal> SquareForCivil() { return (width,hight)=>width*hight; }
Gewerbe- und Wohngebiet:
public Func<int, int, decimal> SquareForBusiness() { return (width, hight) => width * hight*1.2m; }
Diese Funktionen haben alle eine gemeinsame Signatur: Func
public decimal PropertyFee(decimal price,int width,int hight, Func<int, int, decimal> square) { return price*square(width, hight); }
Ist das nicht ganz einfach? Schreiben Sie einen Test und sehen Sie sich
[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); }
an 2. Faule Bewertung
C# verwendet bei der Ausführung eine strikte Auswertungsstrategie. Die sogenannte strikte Auswertung bedeutet, dass Parameter ausgewertet werden, bevor sie an die Funktion übergeben werden. Ist diese Erklärung noch etwas unklar? Schauen wir uns ein Szenario an: Es muss eine Aufgabe ausgeführt werden, die erfordert, dass die aktuelle Speichernutzung weniger als 80 % beträgt und das Ergebnis der vorherigen Berechnung
Wir können schnell C#-Code schreiben, der diese Anforderung erfüllt:
public double MemoryUtilization() { //计算目前内存使用率 var pcInfo = new ComputerInfo(); var usedMem = pcInfo.TotalPhysicalMemory - pcInfo.AvailablePhysicalMemory; return (double)(usedMem / Convert.ToDecimal(pcInfo.TotalPhysicalMemory)); } public int BigCalculatationForFirstStep() { //第一步运算 System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2)); Console.WriteLine("big calulation"); FirstStepExecuted = true; return 10; } public void NextStep(double memoryUtilization,int firstStepDistance) { //下一步运算 if(memoryUtilization<0.8&&firstStepDistance<100) { Console.WriteLine("Next step"); } }
Wenn Sie NextStep ausführen, müssen Sie die Speichernutzung und das Berechnungsergebnis des ersten Schritts übergeben (Funktion BigCalculationForFirstStep). Wie im Code gezeigt, ist der Vorgang des ersten Schritts aufgrund der strengen Bewertungsstrategie ein sehr zeitaufwändiger Vorgang von C#, für Anweisungen If (memoryUtilization
Lazy Evaluation bedeutet also, dass Ausdrücke oder Teile von Ausdrücken nur dann ausgewertet werden, wenn ihre Ergebnisse tatsächlich benötigt werden. Wir versuchen, diese Anforderung mit Funktionen höherer Ordnung umzuschreiben:
public void NextStepWithOrderFunction(Func<double> memoryUtilization,Func<int> firstStep) { if (memoryUtilization() < 0.8 && firstStep() < 100) { Console.WriteLine("Next step"); } }
Der Code ist sehr einfach. Verwenden Sie einfach einen Funktionsausdruck, um den Funktionswert zu ersetzen. Wenn (memoryUtilization() -Klasse können Sie diesen Mechanismus in Szenarien verwenden, in denen ein solcher Bedarf besteht 3. Funktion Curry
Currying wird auch Teilanwendung genannt. Definition: Es handelt sich um eine Technologie, die eine Funktion, die mehrere Parameter akzeptiert, in eine Funktion umwandelt, die einen einzelnen Parameter akzeptiert (den ersten Parameter der ursprünglichen Funktion), und eine neue Funktion zurückgibt, die die verbleibenden Parameter akzeptiert und ein Ergebnis zurückgibt. PS: Warum Ist die offizielle Erklärung so verwirrend?
Angesichts einer solchen Definition ist es wahrscheinlich für jeden schwer zu verstehen, was das ist. Beginnen wir also mit dem Curry-Prinzip:
Schreiben Sie eine Funktion, die zwei Zahlen addiert:
OK, wie verwende ich diese Funktion?public Func<int, int, int> AddTwoNumber() { return (x, y) => x + y; }1+2=3, der Aufruf ist sehr einfach. Um unsere Anforderungen zu verbessern, benötigen wir eine Funktion, die die Eingabe eines Parameters (Zahl) erfordert und das Ergebnis aus 10 + dem Eingabeparameter (Zahl) berechnet. Ich denke, jemand wird sagen, dass der obige Code diese Anforderung vollständig erfüllen kann. Wenn Sie 10 als ersten Parameter übergeben, ist alles in Ordnung. Wenn Sie das glauben, habe ich nichts zu tun. Andere haben vielleicht gesagt, dass das Schreiben einer weiteren Überladung nur einen Parameter erfordert, aber die tatsächliche Situation ist nicht zulässig. Wir rufen die von anderen bereitgestellte API auf und können keine Überladungen hinzufügen. Es ist ersichtlich, dass das Verwendungsszenario der teilweisen Anwendung kein sehr häufiges Szenario ist. Daher besteht das beste Design darin, die entsprechende Technologie in die entsprechende Szene zu integrieren. Schauen wir uns die Implementierung der teilweisen Anwendung an:
var result= _curringReasoning.AddTwoNumber()(1,2);Die Funktionssignatur, die durch den Ausdruck x => y => Function vom Typ int> erhalten wird. Wenn wir um diese Zeit noch einmal anrufen:
public Func<int, Func<int, int>> AddTwoNumberCurrying() { Func<int, Func<int, int>> addCurrying = x => y => x + y; return addCurrying; }
//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); }
同样的道理,Action签名的函数也可以自动套用
有了这些扩展方法,使用局部套用的时候就更加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(' ').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, 如果函数参数改为Expression
Das obige ist der detaillierte Inhalt vonDetaillierte Einführung in den Beispielcode für die funktionale Programmierung in C#. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Zu den neuesten Entwicklungen und Best Practices in der C#.NET-Entwicklung gehören: 1. Asynchrone Programmierung verbessert die Reaktionsfähigkeit der Anwendungen und vereinfacht nicht blockierende Code mit Async und wartet Keywords. 2. LINQ liefert leistungsstarke Abfragefunktionen, die Daten effizient durch verzögerte Ausführung und Ausdrucksbäume manipulieren. 3. Die Vorschläge zur Leistungsoptimierung umfassen die Verwendung der asynchronen Programmierung, die Optimierung von LINQ -Abfragen, die rationale Verwaltung des Speichers, die Verbesserung der Code -Lesbarkeit und -wartung und das Schreiben von Unit -Tests.

Wie erstelle ich Anwendungen mit .NET? Erstellen Anwendungen mit .NET können in den folgenden Schritten erreicht werden: 1) Verstehen Sie die Grundlagen von .NET, einschließlich C# Sprache und plattformübergreifender Entwicklungsunterstützung; 2) Kernkonzepte wie Komponenten und Arbeitsprinzipien des .NET -Ökosystems lernen; 3) Master Basic und Advanced Nutzung, von einfachen Konsolenanwendungen bis hin zu komplexen Webapis- und Datenbankvorgängen; 4) Mit gemeinsamen Fehlern und Debugging -Techniken wie Konfigurations- und Datenbankverbindungsproblemen vertraut sein; 5) Optimierung der Anwendungsleistung und Best Practices wie asynchrone Programmieren und Zwischenspeichern.

C# wird häufig in Anwendungen auf Unternehmensebene, Spieleentwicklung, mobilen Anwendungen und Webentwicklung verwendet. 1) In Anwendungen auf Unternehmensebene wird C# häufig für ASP.NetCore zur Entwicklung von WebAPI verwendet. 2) In der Spielentwicklung wird C# mit der Unity Engine kombiniert, um die Rollenkontrolle und andere Funktionen zu realisieren. 3) C# unterstützt Polymorphismus und asynchrone Programmierung, um die Code -Flexibilität und die Anwendungsleistung zu verbessern.

C# und .NET eignen sich für Web-, Desktop- und Mobile -Entwicklung. 1) In der Webentwicklung unterstützt ASP.NetCore die plattformübergreifende Entwicklung. 2) Die Desktop -Entwicklung verwendet WPF und Winforms, die für unterschiedliche Anforderungen geeignet sind. 3) Mobile Entwicklung realisiert plattformübergreifende Anwendungen über Xamarin.

Das C#.NET -Ökosystem bietet reichhaltige Frameworks und Bibliotheken, mit denen Entwickler Anwendungen effizient erstellen können. 1.asp.netcore wird verwendet, um Hochleistungs-Webanwendungen zu erstellen. Durch das Verständnis der Nutzung und Best Practices dieser Tools können Entwickler die Qualität und Leistung ihrer Anwendungen verbessern.

Wie bereitete ich eine C# .NET -App für Azure oder AWS bereit? Die Antwort ist, AzureAppservice und Awselasticbeanstalk zu verwenden. 1. Automatisieren Sie bei Azure die Bereitstellung mit AzureAppservice und AzurePipelines. 2. Verwenden Sie bei AWS Amazon ElasticbeanSpalk und AWSLambda, um Bereitstellungen und serverlosen Computer zu implementieren.

Die Kombination von C# und .NET bietet Entwicklern eine leistungsstarke Programmierumgebung. 1) C# unterstützt Polymorphismus und asynchrone Programmierung, 2) .NET bietet plattformübergreifende Funktionen und gleichzeitige Verarbeitungsmechanismen, wodurch sie in der Entwicklung von Desktop-, Web- und mobilen Anwendungen häufig verwendet werden.

.NetFramework ist ein Software -Framework, und C# ist eine Programmiersprache. 1..NetFramework bietet Bibliotheken und Dienste, die Desktop-, Web- und mobile Anwendungsentwicklung unterstützen. 2.C# ist für .Netframework entwickelt und unterstützt moderne Programmierfunktionen. 3..NETFRAMEWORK verwaltet die Codeausführung über CLR, und der C# Code wird in IL zusammengestellt und wird von CLR ausgeführt. V. 5. Zu den häufigen Fehlern zählen Typenkonvertierung und asynchrone Programmieradrocken. Visualstudio -Tools sind zum Debuggen erforderlich.


Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

EditPlus chinesische Crack-Version
Geringe Größe, Syntaxhervorhebung, unterstützt keine Code-Eingabeaufforderungsfunktion

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Herunterladen der Mac-Version des Atom-Editors
Der beliebteste Open-Source-Editor
