内容简介:Many popular languages support the use ofLocal functions are private methods of a type that are nested in another member. They can only be called from their containing member. Local functions can be declared in and called from:As with most things, sometime
Many popular languages support the use of local functions and in C# 7, support for them was announced with relatively little fanfare. As someone that would consider themselves a C# power-user, I seldom took advantage of the feature until I realized just how much it could help with making code more readable, specifically in the context as a replacement for comments/hacks, unit tests, and in general just to clean things up.
What are local functions exactly?
Local functions are private methods of a type that are nested in another member. They can only be called from their containing member. Local functions can be declared in and called from:
- Methods, especially iterator methods and async methods
- Constructors
- Property accessors
- Event accessors
- Anonymous methods
- Lambda expressions
- Finalizers
As with most things, sometimes, it's easier to just show you what a local function looks like:
public static IEnumerable<Address> SanitizeAddresses(List<Address> addresses) { foreach(Address address in addresses) { yield return Anonymize(address); } // This is a local function Address Anonymize(Address address) { ... } }
Cleaning Up Comments with Local Functions
One of the first use cases that comes to mind that functions can help alleviate is any pesky sanitation or business logic rules, particularly those around string manipulation, etc. If you've worked in enough business applications, you've undoubtably seen something terrible with some massive comment as to why it's being done:
public static User ProcessUser(User user) { // All names must conform to some crazy Dr. Seuss-eqsue rhyming scheme // along with every other character being placed by it's closest numerically // shaped equivalent var seussifyExpression = new Regex("..."); user.Name = seussifyExpression.Replace(user.Name, "..."); user.Name = user.Name .Replace(..., ...) .Replace(..., ...) .Replace(..., ...); // Other processes omitted for brevity return user; }
As you can see here, we have a series of chained replacements, some relying on strings, and others relying on regular expressions, which can make a method pretty clunky, especially if there's multiple operations to perform. Now, this is where you can define a local function to encapsulate all this business logic to replace your crazy comment:
public static User ProcessUser(User user) { SanitizeName(user) // Other processes omitted for brevity return user; void SanitizeName(User user) { var seussifyExpression = new Regex("..."); user.Name = seussifyExpression.Replace(user.Name, "..."); user.Name = user.Name .Replace(..., ...) .Replace(..., ...) .Replace(..., ...); return user; } }
You could easily name your local function whatever you like, even ApplyBusinessLogicNamingRules()
and include any necessary comments for reasoning that you'd like within there (if you absolutely need to answer why you are doing something), but this should help the rest of your code tell you what it's doing without a comment explicitly writing it all out.
Going All Reading Rainbow with Local Functions
If readability isn't the single most important thing about code, then it's damn close to the top.
LINQ is another popular area that local functions can assist with, especially if you have to do any type of crazy filtering logic over a series of records. You can define a series of local functions that can cover each step of your filtering process (or any process really), and more easily reason about your code from a readability perspective:
public List<int> FindPrimesStartingWithASpecificLetter(List<int> numbers, int startingDigit) { return numbers.Where(n => n > 1 && Enumerable.Range(1, n).Where(x => n % x == 0).SequenceEqual(new [] {1, n })) .Where(n => $"{n}".StartsWith($"{startingDigit}")); }
While succinct, it doesn't exactly read well. Let's take a gander at what it looks like after rubbing some local functions on it:
public List<int> FindPrimesStartingWithASpecificLetter(List<int> numbers, int startingDigit) { return numbers.Where(x => IsPrime(x) && StartsWithDigit(x, startingDigit)); bool IsPrime(int n) => return n > 1 && Enumerable.Range(1, n).Where(x -> n % n == 0).SequenceEqual(new [] { 1, n })); bool StartsWithDigit(int n, int startingDigit) => return $"{n}".StartsWith($"{startingDigit}"); }
As you can see, local functions are assisting with wrapping up all the ugly/nasty logic within their own tiny little functions. This is a really trivial case, but as you might imagine if you have lines-upon-lines of code that isn't touching anything outside of one method, it's likely a solid candidate for a local function.
Testing, Testing, Lo-ca-lly!
If you've spent any amount of time writing tests, either unit or integration, you are probably familiar with the fabled 'Arrange-Act-Assert` pattern, which is used to separate each piece of functionality when testing a given piece of code as follows:
- Arrange all necessary preconditions and inputs.
- Act on the object or method under test.
- Assert that the expected results have occurred.
As you might imagine, this could lend itself to the pattern quite well for complex test cases:
public void IsThisAnArrangeActAssertLocalFunction() { Arrange(); Act(); Assert(); Arrange() { ... } Act() { ... } Assert() { ... } }
Is it practical? Does it fit all use cases? Is it something that you'd ever find yourself using? The answers to all of these might be an overwhelming no, but it does seem like a scenario where local functions could play a role.
Choose Your Own Adventure
Local functions present a few interesting options that fit some scenarios better than others. As a replacement for large comments or very messy business logic - absolutely. In unit tests or little one liners - probably not. With most new features, especially those that are sugary, it's really up to you and your team to see if they work for you. While they may seem appealing in some situations, they also seem ripe for abuse, potentially cluttered methods, and other issues that would completely defeat the purpose of using them in the first place.
So, if you choose to go down this road of local functions, proceed with care.
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
视觉SLAM十四讲
高翔、张涛、等 / 电子工业出版社 / 2017-3 / 75
《视觉SLAM十四讲:从理论到实践》系统介绍了视觉SLAM(同时定位与地图构建)所需的基本知识与核心算法,既包括数学理论基础,如三维空间的刚体运动、非线性优化,又包括计算机视觉的算法实现,例如多视图几何、回环检测等。此外,还提供了大量的实例代码供读者学习研究,从而更深入地掌握这些内容。 《视觉SLAM十四讲:从理论到实践》可以作为对SLAM 感兴趣的研究人员的入门自学材料,也可以作为SLAM......一起来看看 《视觉SLAM十四讲》 这本书的介绍吧!