4 practice C# questions for intermediate level

In this article you can find four C# language specific questions for intermediate level with answers and explained code examples.

1. Given an array of ints, write a C# method to sum all the values that are even numbers.

There are of course many ways to do this, but the best and straightforward way would be using LINQ:

long SumOfEvenNumbers(int[] intArray)
{
    return intArray.Where(i => i % 2 == 0).Sum(i => (long)i);
}

or:

long SumOfEvenNumbers(int[] intArray)
{
    return (from i in intArray where i % 2 == 0 select (long)i).Sum();
}

You may want to use loop to calculate result like this:

int SumOfEvenNumbers(int[] intArray)
{
    int sum = 0;
    foreach (var i in intArray)
    {
         if (i % 2 == 0)
         {
             s += i;
         }
    }

    return sum;
}

And this is a viable solution, but usage of LINQ will show that you are familiar with this technology and you can find shortest straightforward solution to solve problem. Also, LINQ examples consider the possibility of overflow (even sum of two large enough int might cause integer overflow exception), so using long is a good practice which emphasizes your awareness about posibility of overflow exception. Although it doesn't eliminate such posibility completely, using long significantly reduces it.

2. What is the output of the program below? Why?

static void Main()
{
    var delegates = new List<Action>();
    for (int i = 0; i < 10; i++)
    {
        delegates.Add(delegate { Console.WriteLine(i); });
    }

    foreach (var delegate in delegates)
    {
        delegate();
    }
}

The output will be the number "10" ten times. The delegate is added in the for loop and reference to i variable is stored, rather than the value itself. So, after we exit the loop, the variable i has been set to "10" (last state of i in the loop) and by the time each delegate is invoked, the value used by all of them is "10". This behavior known as closure.

3. How to make code example above to print numbers from 1 to 10?

The way around this is to store the value you need in a copy of i variable, and have that copy get captured in closure:

static void Main()
{
    var delegates = new List<Action>();
    for (int i = 0; i < 10; i++)
    {
        int copy = i;
        delegates.Add(delegate { Console.WriteLine(copy); });
    }

    foreach (var delegate in delegates)
    {
       delegate();
    }
}

Each time we go through the loop we're said to get a different instance of the copy variable - each delegate captures a different variable.

Also, there is hidden trick in code above. You can't name variable delegate in foreach, it is reserved keyword in C#.

4. Is the comparison of time and null in the if statement below valid or not?

DateTime time;
void CompareDateTime()
{
    if (time == null)
    {
        /* is it true? */
    }
}

First of all, you need to remember that DateTime is not a reference type (it's a value type), so default value (all fields has default value assigned to them during class instantiation) for it is not null, but the date "Jan 1, 0001". So you might think that compiler would complain when DateTime variable is compared to null. However, due to type coercion, the compiler does allow it. The == operator will cast its operands to different allowable types in order to get a common type on both sides, which it can then compare. In code above, both the DateTime variable and the null literal can be cast to Nullable<DateTime>. Therefore it is legal to compare the two values, even though the result will always be false.

Same logic can be applied to any value type, not only DateTime: int, long, struct, even bool:

if (false == null)
{
    /* it is not true! */
}

Similar articles

Comments