In the first part, this is interesting for value types.
There is not much difference with reference types, you work with the object by the original link or by its copy. But with value types, such as int , you get a copy of the value. For the ref returned, you can work with the original.
Thus, you reduce the amount of copying structures (which can be a problem in high-performance code).
In addition, you can write code like “find a point with the largest X and increase its Y ”, because it looks like functions like
ref Point MaxBy(Point[] points, Func<Point, double> selector) { ref Point result = ref points[0]; for (int i = 1; i < points.Length; i++) if (selector(result) < selector(point[i])) result = ref point[i]; return result; } ref Point rightmost = MaxBy(points, p => pX); rightmost.Y += 1;
Regarding local functions, it seems to me that, on the contrary, often private functions of classes are used as a crutch in the absence of local functions. Often, a helper from a single function that has no value inside a class is taken to a private function. The local function is the more correct path for such functions.
Additionally, local functions “see” local variables in the enclosing function, which means you don’t have to pass a bunch of auxiliary arguments to them.
Another use case for local functions is iterators and async functions. See it. If you have a code
IEnumerable<int> GetOdd(IEnumerable<int> s) { if (s == null) throw new ArgumentNullException(); foreach (var v in s) if (v % 2 != 0) yield return v; }
- then the check will be performed, and the exception is thrown only after the start of the transfer. That is the code
IEnumerable<int> odds; try { odds = GetOdd(seq); } catch (ArgumentException) { return false; } foreach (var v in odds) Console.WriteLine(v);
will not catch the exception. That is, the user will have to know whether the exception will be thrown during the call or during the transfer.
With local functions, you can write this:
IEnumerable<int> GetOdd(IEnumerable<int> s) { if (s == null) throw new ArgumentNullException(); // обратите внимание, `Inner` без параметров IEnumerable<int> Inner() { foreach (var v in s) if (v % 2 != 0) yield return v; } return Inner(); }
The exception will be thrown right away, when you call GetOdd , and not when enumerating. Obviously, the internal function only makes sense for GetOdd , so you should not set up a separate function for it at the external level, even if it is a private one.
returnie If you look at php, then$object1 = find()and object$object2 = find()are different objects. and if you just return the link is the same object. The approach is good for implementing the so-called register pattern, in whichobject1will be equal toobject2. - NaumovMax(ref a, ref b, ref c) = 10;- selection of the maximum of the arguments and assigning it a value. If we return a structure, it will not be necessary to create a copy of it. 2. One-time helper methods (it looks almost like lambda, only without allocating memory for the delegate). I wonder if you can use closures. - kmv