C# Loops – Benefits of Foreach-Loop vs Body-Less For-Loop

cloops

In C# you can use a for-loop without declaring the body, what is the benefit of using this in production-code versus using a foreach loop?

Example

My Examples below use reflection to get the property value of an object based on the p_strPropertyPath parameter. The method can also look at the property of a property, for example MyClass.Property.SubProperty.

In my opinion, the foreach loop is more obvious at what it is supposed to do, whereas the former looks cleaner to me.

Body-less For Loop

The example below uses a body-less for-loop and an enumerator:

private string GetValue(MyClass p_objProperty, string p_strPropertyPath)
{
    string[] lstProperties = p_strPropertyPath.Split('.');
    IEnumerator objEnumerator = lstProperties.GetEnumerator();

    object objValue;

    for (
        objValue = p_objProperty;
        objValue != null && objEnumerator.MoveNext();
        objValue = objValue.GetType().GetProperty(objEnumerator.Current as string).GetValue(objValue)
        ) ;

    return Convert.ToString(objValue);
}

foreach loop

The example below uses a foreach loop:

private string GetValue(MyClass  p_objProperty, string p_strPropertyPath)
{
    string[] lstProperties = p_strPropertyPath.Split('.');
    object objValue = p_objProperty;
    foreach (string strProperty in lstProperties)
    {
        objValue = objValue.GetType().GetProperty(strProperty).GetValue(objValue);
        if(objValue == null) break;
    }

    return Convert.ToString(objValue);
}

Best Answer

Your suggested code is not equivalent if lstProperties is empty, (as ErikEidt points out, also if it is non-empty), if p_objProperty is null, or if .GetValue() returns null. All of those cases are quite relevant because the shown function is using reflection to traverse an object graph.

A for-loop without a body can be an elegant description when searching for a certain value, or when the loop body already happens as a side effect of the loop condition.

I don't think the shown code is a fantastic example of this feature, because both the loop condition and the iterator section have side effects. A classic for-loop is most applicable when all sections are fairly simple. It may be clearer to de-sugar the for-loop into a while loop, mostly because the code is a bit too complex for a single line:

object value = initialValue;
while (value != null && enumerator.MoveNext())
{
    var propertyName = enumerator.Current as string;
    value = value.GetType().GetProperty(propertyName).GetValue(value);
}

If you were to use a foreach loop, take care to convert the exact loop condition, e.g. by breaking from the loop:

object value = initialValue;
foreach (string propertyName in properties)
{
    if (value == null) {
        break;
    }
    value = value.GetType().GetProperty(propertyName).GetValue(value);
}