C# yield return 101!

One of the basic tasks that usually I do is getting data from the database, change it into another object, and then process it.
For instance, if you have this data:

var details = new[]
{
	new Person {TypeId = 1, Name = "Dafid", Amount = 1000m},
	new Person {TypeId = 1, Name = "Satrio", Amount = 750m},
	new Person {TypeId = 2, Name = "John", Amount = 500m}
};

var informations = new[]
{
	new Information {TypeId = 1, Description = "Member", Disc = 0.25m},
	new Information {TypeId = 2, Description = "Non-Member", Disc = 0.15m}
};

When you want to process it into this data type:

public class PriceDetail
{
	public string Name { get; set; }
	public string TypeDescription { get; set; }
	public decimal Amount { get; set; }
	public decimal DiscRate { get; set; }
	public decimal DiscAmount { get; set; }
	public decimal TotalPayable { get; set; }
}

Then if you create a function to change the data, usually we achieve it using this way:

private PriceDetail[] GetPriceDetails(Person[] details, Information[] informations)
{
	var result = new List();
	foreach (var detail in details)
	{
		var name = detail.Name;
		var typeId = detail.TypeId;
		var amount = detail.Amount;
		var info = informations.First(e => e.TypeId == typeId);

		var discRate = info.Disc;
		var typeDescription = info.Description;
		var discAmount = amount * discRate;
		var totalPayable = amount - discAmount;

		result.Add(new PriceDetail
		{
			Name = name,
			Amount = amount,
			DiscAmount = discAmount,
			DiscRate = discRate,
			TotalPayable = totalPayable,
			TypeDescription = typeDescription
		});
	}

	return result.ToArray();
}

Using IEnumerable, we can do like this:

private IEnumerable GetPriceDetails(Person[] details, Information[] informations)
{
	foreach (var detail in details)
	{
		var name = detail.Name;
		var typeId = detail.TypeId;
		var amount = detail.Amount;
		var info = informations.First(e => e.TypeId == typeId);

		var discRate = info.Disc;
		var typeDescription = info.Description;
		var discAmount = amount * discRate;
		var totalPayable = amount - discAmount;

		yield return new PriceDetail
		{
			Name = name,
			Amount = amount,
			DiscAmount = discAmount,
			DiscRate = discRate,
			TotalPayable = totalPayable,
			TypeDescription = typeDescription
		};
	}
}

Conclusion

IEnumerable function is lazy by default or it means that the function will not execute until you need the result. That’s why it will be dangerous if you are not know how to use it.

If you put Console.WriteLine(“Called”) on GetPriceDetails method and then call this code (in picture below). The result showed that GetPriceDetails will be called 2 times.

If you put ToArray after calling GetPriceDetails, it will be called 1 time only.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.