Mohammed Omar's Blog

Just another WordPress.com site

Tag Archives: Func

Why the Yield return is Important!

You should always use yield when possible specially between layers, actually if it wasn’t for yield many features would be really hard to implement nowadays and to hear you say you don’t use it makes me wonder how you implement those features. Any way lets analysis some code:

Consider the following piece of code:

          public IEnumerable<int> Dolist()
        {
            List<int> nums = new List<int>();
            for (int i = 0; i < 5; i++)
            {
                nums.Add(i);
            }

            return nums;
        }

Looks so simple and straight forward isn’t it? We iterate over 5 digits add them to a list and return them…
So straight forward… now compile your code to dll and then disassemble it then check how the compiler compiled your code:

public class Class1
{
    // Methods
    public IEnumerable<int> Dolist()
    {
        List<int> nums = new List<int>();
        for (int i = 0; i < 5; i++)
        {
            nums.Add(i);
        }
        return nums;
    }
}

Nothing strange here everything is as expected…

Now try this code :

public IEnumerable<int> DoEnum()
        {
            for (int i = 0; i < 5; i++)
            {
                yield return i;
            }
        }

Now check the Compiled code:

public class Class1
{
    // Methods
    public IEnumerable<int> DoEnum()
    {
        <DoEnum>d__0 d__ = new <DoEnum>d__0(-2);
        d__.<>4__this = this;
        return d__;
    }

    // Nested Types
    [CompilerGenerated]
    private sealed class <DoEnum>d__0 : IEnumerable<int>, IEnumerable, IEnumerator<int>, IEnumerator, IDisposable
    {
        // Fields
        private int <>1__state;
        private int <>2__current;
        public Class1 <>4__this;
        private int <>l__initialThreadId;
        public int <i>5__1;

        // Methods
        [DebuggerHidden]
        public <DoEnum>d__0(int <>1__state)
        {
            this.<>1__state = <>1__state;
            this.<>l__initialThreadId = Thread.CurrentThread.ManagedThreadId;
        }

        private bool MoveNext()
        {
            switch (this.<>1__state)
            {
                case 0:
                    this.<>1__state = -1;
                    this.<i>5__1 = 0;
                    while (this.<i>5__1 < 5)
                    {
                        this.<>2__current = this.<i>5__1;
                        this.<>1__state = 1;
                        return true;
                    Label_0046:
                        this.<>1__state = -1;
                        this.<i>5__1++;
                    }
                    break;

                case 1:
                    goto Label_0046;
            }
            return false;
        }

        [DebuggerHidden]
        IEnumerator<int> IEnumerable<int>.GetEnumerator()
        {
            if ((Thread.CurrentThread.ManagedThreadId == this.<>l__initialThreadId) && (this.<>1__state == -2))
            {
                this.<>1__state = 0;
                return this;
            }
            Class1.<DoEnum>d__0 d__ = new Class1.<DoEnum>d__0(0);
            d__.<>4__this = this.<>4__this;
            return d__;
        }

        [DebuggerHidden]
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.System.Collections.Generic.IEnumerable<System.Int32>.GetEnumerator();
        }

        [DebuggerHidden]
        void IEnumerator.Reset()
        {
            throw new NotSupportedException();
        }

        void IDisposable.Dispose()
        {
        }

        // Properties
        int IEnumerator<int>.Current
        {
            [DebuggerHidden]
            get
            {
                return this.<>2__current;
            }
        }

        object IEnumerator.Current
        {
            [DebuggerHidden]
            get
            {
                return this.<>2__current;
            }
        }
    }
}

WHAT!????? So it’s not that you just don’t want to declare a variable to hold numbs! What is it then?

As you can see the .Net compiler would take your Code and compile it to a helper class which serve a State nested Class, to hold the state of every time you retrieve an item of the enumerator, which in other word you don’t get all the items at once! , it LAZY retrieve the items when you for each them which is perfect for LINQ! (isn’t that what LINQ is about?), so what! what advantage that would give me ?

Performance

Try the same implementation with 100 million numbers you will be amazed on the performance you get with a simple keyword (Yield), but guess what this is not all !

Yield return is one of the many keywords that Microsoft put into C# to support LINQ, part of the fact that LINQ is Lazy, let me put this into real example here and show you what you would gain from the Yield return keyword:

Consider this code:

public static class CustomerRepository
    {
        public static IEnumerable<Customer> GetAllNotLazy()
        {
            List<Customer> customers = new List<Customer>();

            for (int i = 0; i < 10; i++)
            {
                customers.Add(new Customer()
                                  {
                                      FirstName = "Mohammed",
                                      LastName = "Umar"
                                  });
            }
            return customers;
        }
        public static IEnumerable<Customer> GetAllLazy()
        {
            for (int i = 0; i < 10; i++)
            {
                yield return new Customer()
                    {
                        FirstName = "Mohammed",
                        LastName = "Umar"
                    };
            }
        }
    }

Now consider you`re in another layer or something with this code:

public static void Main()
        {
            var NotLazy = CustomerRepository.GetAllNotLazy().Where(x =>x.FirstName == "Mohammed");
            var Lazy = CustomerRepository.GetAllLazy().Where(x => x.FirstName == "Mohammed");
            foreach (var customer in Lazy)
            {
                //do stuff
            }
            foreach (var customer in NotLazy)
            {
                //do stuff
            }
        }

With GetAllNoLazy all your objects would be retrieved at once!
With GetAllLazy your objects would be retrieved once you need them!

Imagine you were checking something or applying some filter while your iterating inside the for-each and you decided to break! With lazy you wouldn’t lose much, without being lazy all your objects would be in memory anyway despite the fact that you break or not!

I can go on and on with situation where not using “Yield Return” would be a crime!

But I can sure now you can realize how the yield return was mandatory for LINQ and what situation you must use it otherwise implement your own State-Class…

Path 2 Expression Trees

In the beginning!      
               It all started with LINQ2SQL and the need for making a good Web Application Architecture, making loosely coupled layers and separating concerns, the fact that we need to transfer lambda expressions between layers to support fully function interfaces for search made me start thinking about how LINQ2SQL really works, to be honest i never thought i would be digging into Expression treeS i thought its all about just making methods which expect Lambda Expression and passing them through layers, here is some facts i went through:   

  • I need away to transfer Lambda Expression between layers.
  • Since layers should`nt know nothing about upper layers i need to find away to translate lambda expression parameters types to fit the need of lower layers as long as it travel deeper and deeper through layers.
  • I needed to support MemberAccess expressions, Method Calls, almost all kind of Expression Types to allow fully functional Lambda expression.

                     So any way after i made all this possible i decided to start a learning Path toward the Expression Trees and i decided to blog that path, i will start posting almost everything i needed to learn to get to Expression Trees and then im willing to post everything i learn about Expression trees, so far in the next Posts i will be writing the following topics in this order:    

  1. Delegates.
  2. Anonymous Delegates.
  3. Lambda Expressions.
  4. evolution of Predicate (Func/Action).
  5. ExpressionTrees.

              I would also like to make it clear that most of the info im going to provide i learned by searching and by other articles, but i never find any place that i could learn about expression trees from A to Z,  that is why i thought of starting this series of posts, hoping it will give developers who wants to learn about Expression Tree what i couldnt find any where.  

see you in several coming Posts.