After almost 4 years of experience, I haven't seen a code where yield keyword is used. Can somebody show me a practical usage (along explanation) of this keyword, and if so, aren't there other ways easier to fullfill what it can do?
Efficiency

The yield keyword effectively creates a lazy enumeration over collection items that can be much more efficient. For example, if your foreach loop iterates over just the first 5 items of 1 million items then that's all yield returns, and you didn't build up a collection of 1 million items internally first. Likewise you will want to use yield with IEnumerable<T> return values in your own programming scenarios to achieve the same efficiencies.

Example of efficiency gained in a certain scenario

Not an iterator method, potential inefficient use of a big collection,
(Intermediate collection is built having lots of items)

// Method returns all million items before anything can loop over them. 
List<object> GetAllItems() {
    List<object> millionCustomers;
    database.LoadMillionCustomerRecords(millionCustomers); 
    return millionCustomers;
}

// MAIN example ---------------------
// Caller code sample:
int num = 0;
foreach(var itm in GetAllItems())  {
    num++;
    if (num == 5)
        break;
}
// Note: One million items returned, but only 5 used. 


Iterator version, efficient
(No intermediate collection is built)

// Yields items one at a time as the caller's foreach loop requests them
IEnumerable<object> IterateOverItems() {
    for (int i; i < database.Customers.Count(); ++i)
        yield return database.Customers[i];
}

// MAIN example ---------------------
// Caller code sample:
int num = 0;
foreach(var itm in IterateOverItems())  {
    num++;
    if (num == 5)
        break;
}
// Note: Only 5 items were yielded and used out of the million.


Simplify some programming scenarios

In another case, it makes some kinds of sorting and merging of lists easier to program because you just yield items back in the desired order rather than sorting them into an intermediate collection and swapping them in there. There are many such scenarios. 

Just one example is the merging of two lists: 

IEnumerable<object> EfficientMerge(List<object> list1, List<object> list2) {
    foreach(var o in list1) 
        yield return o; 
    foreach(var o in list2) 
        yield return o;
}


This method yields back one contiguous list of items, effectively a merge with no intermediate collection needed. 

More Info

The yield keyword can only be used in context of an iterator method (having a return type of IEnumerable, IEnumerator, IEnumerable<T>, or IEnumerator<T>.) and there is a special relationship with foreach. Iterators are special methods. The MSDN yield documentation and iterator documentation contains lots of interesting information and explanation of the concepts. Be sure to correlate it with the foreach keyword by reading about it too, to supplement your understanding of iterators.

To learn about how the iterators achieve their efficiency, the secret is in the IL code generated by the C# compiler. The IL generated for an iterator method differs drastically from that generated for a regular (non-iterator) method. This article (What Does the Yield Keyword Really Generate?) provides that kind of insight. 
