介绍 自从我开始了解扩展方法以来,我不断地发现新的可能性,让我的编码生活更轻松。扩展方法是SOLID完美应用中的O开闭原则。一个类应该尽可能简单,并且只在其他组件真正需要时才将属性和方法暴露给外部。 通过扩展方法,您可以为您的类实现额外的方法,而无需更改类本身!这非常适合将类作为参数的重复方法。 实现扩展方法非常简单。看看下面的例子:namespaceSystem;publicstaticclassEnumerableExtensions{publicstaticvoidForEachT(thisIEnumerableTsequence,ActionTaction){foreach(variteminsequence)action(item);}} 这在每个IEnumerable(由this关键字引入)上实现了ForEach()方法,就像您从List类型中了解到的那样。要访问此方法,您唯一需要做的就是添加对相应命名空间的引用,在本例中为System。我最常用的7种扩展方法 自。NET6以来,Microsoft为IEnumerable实现了一些扩展方法,我之前将这些方法列在了我的首选列表中,包括DistinctBy()和Chunk()。但是,从。NET7开始,我仍然缺少一些非常重要的方法,尤其是处理任务(Task)集合的方法。 事不宜迟,以下是我在。NET7中最常用的扩展方法:1。TryAsync 第一种扩展方法是我最喜欢的一种。您有多少次在刚刚创建的方法周围添加trycatch块,并且因为它破坏了外观而变得有点恼火?当您的方法返回Task或Task时,这是一个非常简洁的解决方案:publicstaticasyncTaskResultTryAsync(thisTasktask,ActionExceptionerrorHandlernull){try{awaittask;returnResult。Ok();}catch(Exceptionex){if(errorHandlerisnotnull)errorHandler(ex);returnex;}}publicstaticasyncTaskResultTTryAsyncT(thisTaskTtask,ActionExceptionerrorHandlernull)whereT:class{try{returnawaittask;}catch(Exceptionex){if(errorHandlerisnotnull)errorHandler(ex);returnex;}} 现在你可以这样写:varresultawaitGetSomethingAsync()。TryAsync(); 您的方法将自动包装在trycatch块中。此外,您可以为其他辅助逻辑(如日志记录)提供errorHandler。然后可以检查这些方法返回的结果是否成功,后续您可以继续您的逻辑。 2。WhenAllAsync 集合中有多个Task或Task以正常方式处理有点不方便。您需要调用Task。WhenAll(tasks)这让我有点脱离流程,因为它不是流畅的风格。这是它的样子:publicstaticasyncTaskIEnumerableTWhenAllAsyncT(thisIEnumerableTaskTtasks){if(tasksisnull)thrownewArgumentNullException(nameof(tasks));returnawaitTask。WhenAll(tasks)。ConfigureAwait(false);}publicstaticTaskWhenAllAsync(thisIEnumerableTasktasks){if(tasksisnull)thrownewArgumentNullException(nameof(tasks));returnTask。WhenAll(tasks);} 现在我可以方便的地处理任何任务集合:varresultsawaittasks。WhenAllAsync();3。WhenAllSequentialAsync 下一个扩展方法甚至可以为您节省几行代码,并让您能够逐个执行每个任务。这在您可能不会并行执行许多任务的情况下很有用。publicstaticasyncTaskIEnumerableTWhenAllSequentialAsyncT(thisIEnumerableTaskTtasks){if(tasksisnull)thrownewArgumentNullException(nameof(tasks));varresultsnewListT();foreach(vartaskintasks)results。Add(awaittask。ConfigureAwait(false));returnresults;}publicstaticasyncTaskWhenAllSequentialAsync(thisIEnumerableTasktasks){if(tasksisnull)thrownewArgumentNullException(nameof(tasks));foreach(vartaskintasks)awaittask。ConfigureAwait(false);}4。WhenAllParallelAsync 最后但同样重要的是,可能有一个用例,您可以并行执行任务,但可能有最大数量限制。对于这种情况,我有以下扩展方法:publicstaticasyncTaskIEnumerableTWhenAllParallelAsyncT(thisIEnumerableTaskTtasks,intdegree){if(tasksisnull)thrownewArgumentNullException(nameof(tasks));varresultsnewListT();foreach(varchunkintasks。Chunk(degree)){varchunkResultsawaitTask。WhenAll(chunk)。ConfigureAwait(false);results。AddRange(chunkResults);}returnresults;}publicstaticasyncTaskWhenAllParallelAsync(thisIEnumerableTasktasks,intdegree){if(tasksisnull)thrownewArgumentNullException(nameof(tasks));foreach(varchunkintasks。Chunk(degree))awaitTask。WhenAll(chunk)。ConfigureAwait(false);} 使用degree参数,您可以指定应并行执行多少个任务。5。MapAsync 这也是一个流畅的扩展,但这次是针对单个Task或Task。publicstaticasyncTaskTOutMapAsyncTIn,TOut(thisTaskTIntask,FuncTIn,TaskTOutmapAsync){if(taskisnull)thrownewArgumentNullException(nameof(task));if(mapAsyncisnull)thrownewArgumentNullException(nameof(mapAsync));returnawaitmapAsync(awaittask);}publicstaticasyncTaskTOutMapAsyncTIn,TOut(thisTaskTIntask,FuncTIn,TOutmap){if(taskisnull)thrownewArgumentNullException(nameof(task));if(mapisnull)thrownewArgumentNullException(nameof(map));returnmap(awaittask);} 使用此扩展方法,您可以将Task流畅地映射到Task,类似于Enumerable。Select()方法。6。DoAsync 类似的方法是DoAsync(),但不是转换任务,而是可以使用任务结果执行辅助逻辑而不改变其返回值。publicstaticasyncTaskTDoAsyncT(thisTaskTtask,FuncT,TasktapAsync){if(taskisnull)thrownewArgumentNullException(nameof(task));if(tapAsyncisnull)thrownewArgumentNullException(nameof(tapAsync));varresawaittask;awaittapAsync(res);returnres;}publicstaticasyncTaskTDoAsyncT(thisTaskTtask,ActionTtap){if(taskisnull)thrownewArgumentNullException(nameof(task));if(tapisnull)thrownewArgumentNullException(nameof(tap));varresawaittask;tap(res);returnres;}7。String。Join 最后一个是我有时用于连接字符串以进行日志记录的扩展方法。通常,您可以为此使用string。Join(),但同样,这并不流畅,让我无法理解。publicstaticstringJoin(thisIEnumerablestringsequence,stringseparator){returnstring。Join(separator,sequence);}缩略 技术上不是扩展方法,但对节省一些代码也很有用,以下是我的缩写方法:namespaceSystem;publicstaticclassAbbreviations{publicstaticIEnumerableTArrT(paramsT〔〕elements)elements;publicstaticvoidTry(Actionaction,ActionException?errorHandlernull){try{action();}catch(Exceptionex){if(errorHandlerisnotnull)errorHandler(ex);}}publicstaticResultTTryT(FuncTaction,ActionException?errorHandlernull)whereT:class{try{returnaction();}catch(Exceptionex){if(errorHandlerisnotnull)errorHandler(ex);returnex;}}} 要轻松使用它们,您必须在根级别创建一个特殊文件(我通常将其称为GlobalUsings。cs)并在其中放入以下行:globalusingstaticSystem。Abbreviations;1。Arr Arr方法是从现有值创建新IEnumerable的缩写。通常,这将需要非常丑陋的代码,如下所示:vararrnew〔〕{param1,param2,。。。}; 现在你可以这样写:vararrArr(param1,param2,。。。); 哪个看起来更漂亮?2。Try 您有多少次只是想在一个新方法周围添加一个简单的trycatch块,但由于它在您的代码中占用了太多空间,所以感觉很难看?这是一个缩写方法Try()的解决方案。 在最短的形式中,你可以写:Try(TestMethod); 其中TestMethod是一个不带任何参数的方法。这使您能够编写极短的代码并消除那些讨厌的trycatch块。 对于异步方法,我建议您使用上面的扩展方法TryAsync,因为它是流畅的风格。 当然,还有更多的可能性,您可以使用此架构并制作自己的缩写词和扩展方法。在评论中让我知道你的想法。 我希望您发现其中一些方法有用并将它们应用到您的项目中。 谢谢阅读!