My previous post posed some C# questions based on some code with incomplete output. This post provides the answers… don’t cheat now…
You will need to see the past post to see the code, but as a reminder, the questions were:
- Fill in the question marks in the output fragment, and explain why.
Also explain what would happen if the int[] parameter to DoSomethingElse was changed to a ref int[]. - Why is it a good idea to use the integerValue.ToString() method in the string.Format arguments?
- Suggest some ways that this code could be improved.
And the output fragment was:
Value of c.Member is ?
Value of s.Member is ?
Value of a[5] is ?
Value of a[5] is now ?
Press a key...
Answers for Question 1
The output would look like this:
Value of c.Member is 42
Value of s.Member is 26
Value of a[5] is 42
Value of a[5] is now 5
Press a key...
The values are set that way because, although all parameters are passed by value some of the types are reference types, so it is a reference to the data that is copied and passed to the methods. In summary:
- The class is a reference type, so a reference is passed to the method, and the same instance of the data member is changed in the method;
- The structure is a value type, so a copy of the structure is passed to the method, the copy is changed in the method, and the calling method retains the original value;
- Even though integers are value types, arrays are reference-types, therefore the DoSomething method call does change the contents of the original array. If someone answers ‘5’ here, you might ask why they think the initA method works to initialise the array, but the DoSomething method does not!
- The DoSomethingElse method call creates a new instance of a reference type. The ‘a’ parameter in that method is a copy of the caller’s reference to the original array; therefore, it is the copy of the pointer that is changed to the new array instance; meaning the assignment to a[5] in the method is changing a copy too. The caller retains it’s value;
- If the DoSomethingElse call was changed to take a ref int[] parameter, the result would be 15 because this time a reference to the integer array reference would be passed, therefore the caller would see the newly constructed and initialised array.
Answers for Question 2
This question is fairly specific to the string.Format method, and understanding that it has to be able to take a variable number of System.Object parameters. The Object type is a reference type, an integer is a value type. If the following coding style had been used:
string.Format("Blah {0}", anInteger)
then the compiler would automatically ‘box’ the integer to pass it as a parameter that will work with the parameter type. The Format method will effectively have to unbox the integer to access it’s ToString() method, and that’s quite an overhead.
Instead, it’s better to pre-convert the integer to a reference type with ToString() yourself, giving you:
string.Format("Blah {0}", anInteger.ToString())
which will avoid the overhead of boxing and unboxing. Granted, that is not much of an overhead unless you are in a tight loop.
Suggested Answer to Question 3
A very vague question with a very vague set of answers, but which are designed to allow the person being tested to ‘complain’ that the example code is contrived.
I’d hope that you will have answered that the DoSomething methods that take a structure or class as parameters could or should be inside the class themselves – this is an appropriate answer as they are written because they only operate on the members of the class and nothing else. Of course, if the methods were moved into the structure and / or class, they would not require parameters any more, and could become instance members.
If I were to follow-up and ask the candidate to write the method as it would need to be written on the structure, for example, I would have the opportunity to enquire whether or not it could be a static method, and so on.