Is revenue useful outside LINQ?

When I think I can use the yield keyword, I take a step back and see how this will affect my project. I always end up returning the collection instead of gaining weight, because I feel that the overhead of maintaining the weight loss method does not buy me much. In almost all cases when I return a collection, I feel that 90% of the time, the calling method will iterate over all elements of the collection or will search for a series of elements throughout the collection.

I understand its usefulness in linq, but I feel that only the linq command writes such complex requested objects that provide usefulness.

Has anyone written something like or unlike linq where profitability was useful?

+26
yield c # linq
Nov 25 '08 at 15:00
source share
14 answers

Recently, I had to make a representation of mathematical expressions as an Expression class. When evaluating an expression, I need to cross the tree structure using a post-ordered triple. For this, I implemented an IEnumerable <T> for example:

public IEnumerator<Expression<T>> GetEnumerator() { if (IsLeaf) { yield return this; } else { foreach (Expression<T> expr in LeftExpression) { yield return expr; } foreach (Expression<T> expr in RightExpression) { yield return expr; } yield return this; } } 

Then I can just use foreach to move the expression. You can also add a property to change the crawl algorithm as needed.

+12
Nov 25 '08 at 17:04
source share

Note that with the lesson you repeat the assembly once, but when you create the list, you will repeat it twice.

Take, for example, a filter iterator:

 IEnumerator<T> Filter(this IEnumerator<T> coll, Func<T, bool> func) { foreach(T t in coll) if (func(t)) yield return t; } 

Now you can link this:

  MyColl.Filter(x=> x.id > 100).Filter(x => x.val < 200).Filter (etc) 

Your method will create (and drop) three lists. My method is repeated only once.

In addition, when you return the collection, you enforce a specific implementation on your users. An iterator is more general.

+27
Nov 25 '08 at 15:05
source share

I understand its usefulness in linq, but I feel that only the linq command writes such complex requested objects that provide usefulness.

The output was useful as soon as it was implemented in .NET 2.0, which was long before anyone thought of LINQ.

Why should I write this function:

 IList<string> LoadStuff() { var ret = new List<string>(); foreach(var x in SomeExternalResource) ret.Add(x); return ret; } 

When can I use the exit and save the effort and complexity of creating a temporary list without a good reason:

 IEnumerable<string> LoadStuff() { foreach(var x in SomeExternalResource) yield return x; } 

It can also have huge performance benefits. If your code uses only the first 5 elements of the collection, then using the crop will often avoid the effort of loading any of this moment. If you create a collection, then return it, you spend a lot of time and space on things that you will never need.

I could go on and on ....

+18
Dec 02 '08 at 23:51
source share

In a previous company, I found myself writing loops as follows:

 for (DateTime date = schedule.StartDate; date <= schedule.EndDate; date = date.AddDays(1)) 

With a very simple iterator block, I was able to change this to:

 foreach (DateTime date in schedule.DateRange) 

This made the code a lot easier to read, IMO.

+11
Nov 25 '08 at 15:24
source share

yield was developed for C # 2 (before Linq in C # 3).

We used it in a large C # 2 enterprise web application to work with data access and highly repetitive computing.

Collections are great anytime you have several elements that you are going to hit several times.

However, in many data access scenarios, you have a large number of elements that you do not need to go around in a large, large collection.

This is essentially what SqlDataReader does - it is a forwarded only user enumerator.

That yield allows you to write your own custom counters quickly and with minimal code.

All yield can be done in C # 1 - it took a lot of code codes.

Linq really maximizes the value of profitability behavior, but it is certainly not the only application.

+8
Nov 25 '08 at 16:12
source share

Whenever your function returns IEnumerable, you should use "yielding". Only in .Net> 3.0.

. Example 2.0 2.0:

  public static class FuncUtils { public delegate T Func<T>(); public delegate T Func<A0, T>(A0 arg0); public delegate T Func<A0, A1, T>(A0 arg0, A1 arg1); ... public static IEnumerable<T> Filter<T>(IEnumerable<T> e, Func<T, bool> filterFunc) { foreach (T el in e) if (filterFunc(el)) yield return el; } public static IEnumerable<R> Map<T, R>(IEnumerable<T> e, Func<T, R> mapFunc) { foreach (T el in e) yield return mapFunc(el); } ... 
+2
Nov 25 '08 at 15:21
source share

I am not sure about the implementation of C # yield (), but in dynamic languages ​​this is much more efficient than creating an entire collection. in many cases, it simplifies working with data sets that are much larger than RAM.

+2
Nov 25 '08 at 15:46
source share

I am a big fan of Yield in C #. This is especially true in large homebuilding frameworks, where often methods or properties return a List, which is a subset of another IEnumerable. The benefits that I see are as follows:

  • the return value of the method using the output is immutable
  • you repeat only once on the list
  • it is a late or lazy execution variable, that is, the code to return the values ​​is not executed until it is needed (although this may bite you if you do not know what you are doing)
  • changes to the original list you do not need to call to get another IEnumerable, you just go through IEnumable again
  • many more

Another HUGE profitability benefit is when your method potentially returns millions of values. So much that there is the potential for running out of memory by simply building a list before a method can even return it. With the exit, the method can simply create and return millions of values, and so far the caller does not save each value either. Thus, it is good for large-scale data processing / aggregation operations.

+2
Jan 27
source share

Personally, I did not find that I use the crop in my usual daily programming. However, I recently started playing with Robotics Studio samples and found that the output is widely used there, so I also see that it is used in conjunction with CCR (Concurrency and reconciliation time), where you have asynchronous and concurrency issues.

Anyway, I'm still trying to hug my head.

+1
Nov 25 '08 at 15:15
source share

The solution is useful because it saves you space. Most programming optimizations compromise between space (disk, memory, network) and processing. Exit as a programming construct allows you to repeatedly iterate over a collection without requiring a separate copy of the collection for each iteration.

consider this example:

 static IEnumerable<Person> GetAllPeople() { return new List<Person>() { new Person() { Name = "George", Surname = "Bush", City = "Washington" }, new Person() { Name = "Abraham", Surname = "Lincoln", City = "Washington" }, new Person() { Name = "Joe", Surname = "Average", City = "New York" } }; } static IEnumerable<Person> GetPeopleFrom(this IEnumerable<Person> people, string where) { foreach (var person in people) { if (person.City == where) yield return person; } yield break; } static IEnumerable<Person> GetPeopleWithInitial(this IEnumerable<Person> people, string initial) { foreach (var person in people) { if (person.Name.StartsWith(initial)) yield return person; } yield break; } static void Main(string[] args) { var people = GetAllPeople(); foreach (var p in people.GetPeopleFrom("Washington")) { // do something with washingtonites } foreach (var p in people.GetPeopleWithInitial("G")) { // do something with people with initial G } foreach (var p in people.GetPeopleWithInitial("P").GetPeopleFrom("New York")) { // etc } } 

(Obviously, you don’t need to use revenue with extension methods, it just creates a powerful paradigm to think about data.)

As you can see, if you have many of these “filtering” methods (but it can be any method that does some work on a list of people), you can link many of them together without requiring additional storage space for each step. This is one way to enhance your programming language (C #) to better express your decisions.

The first side effect of the output is that it delays the execution of the filtering logic until you require it. If you therefore create a variable of type IEnumerable <> (with outputs), but never repeat it, you never execute logic or consume space, which is a powerful and free optimization.

Another side effect is that the output works on the lowest common collection interface (IEnumerable <>), which allows library-like code to be created with wide applicability.

+1
Nov 25 '08 at 15:19
source share

Note that profitability allows you to do things in a "lazy" way. Laziness, I mean that evaluating the next element in IEnumberable is not performed until the element is requested. This allows you to do several different things. First, you can give an infinitely long list without having to do endless calculations. Secondly, you can return the enumeration of functional applications. These functions will be applied only when navigating through the list.

+1
Nov 25 '08 at 17:21
source share

I used yeild in non-linq code, something like this (assuming functions don't live in the same class):

 public IEnumerable<string> GetData() { foreach(String name in _someInternalDataCollection) { yield return name; } } ... public void DoSomething() { foreach(String value in GetData()) { //... Do something with value that doesn't modify _someInternalDataCollection } } 

You must be careful to inadvertently change the collection that your GetData () function is executing, or throw an exception.

0
Nov 25 '08 at 16:03
source share

Profitability is very useful in general. It is in ruby ​​among other languages ​​that support functional style programming, so it binds it to linq. It is the other way around that linq is functional in style, so it uses output.

I had a problem when my program used many processors in some background tasks. I really wanted everyone else to be able to write functions like regular ones so that I could read them easily (i.e. the whole argument related to threads and events). And still you can break functions if they take too much CPU. Perfect for this. I wrote a blog post about this, and the source is available to everyone :)

0
Dec 02 '08 at 23:32
source share

System.Linq IEnumerable extensions are great, but someday you need more. For example, consider the following extension:

 public static class CollectionSampling { public static IEnumerable<T> Sample<T>(this IEnumerable<T> coll, int max) { var rand = new Random(); using (var enumerator = coll.GetEnumerator()); { while (enumerator.MoveNext()) { yield return enumerator.Current; int currentSample = rand.Next(max); for (int i = 1; i <= currentSample; i++) enumerator.MoveNext(); } } } } 

Another interesting benefit of the assignment is that the caller cannot pass the return value to the original type of the collection and change its internal collection.

0
Sep 28 '10 at
source share



All Articles