Quiz Answers

Published February 23, 2010
Advertisement
This post contains the answers to my C# quiz. If you haven't taken it yet, go do so now.

First, I need to say that the point of these types of quizzes isn't to explore commonly used code or exhibit best practices. It's just interesting, at least to me, to see the murky corners of a commonly used language or API. With that said, here are the answers to the C# quiz I posted a few days ago.

Question 1


I am particularly fond of this question, as it has several layers of trickiness to it. Many questions in quizzes like these can be deciphered based upon the very nature of the fact that they're in the quiz to begin with. Naturally, people first thought "well, normally I would say that wouldn't compile, but since this is an esoteric C# quiz, it must compile." The answers were split down the middle, but I didn't find anyone who got the answer right for the right reasons.

The snippet as posted doesn't compile. The error, however, does not deal with identifier names, the @ symbol, or the Unicode escape sequence. The error stems from a small line in the C# standard:
Quote:Delimited comments (the /* */ style of comments) are not permitted on source lines containing pre-processing directives.

I'm not sure exactly why this is, as it's not true in C++, but once that innocuous looking comment is taken out the snippet will compile and run.

Next, we look at the preprocessor directive there. Using C# keywords is valid as preprocessor tokens, so the class is compiled into the program. The @ symbol allows keywords to be used as identifiers, but it doesn't contribute to the identifier's actual name. Several people comment on this as being a rather contrived example, and while I agree that I got a little carried away sticking it on everything, I have run into this symbol in the wild when interoping with a C++/CLI project that used "object" as a parameter name, so knowing this isn't completely useless.

Next, there is the function containing the Unicode escape sequence in its name. Unicode is indeed allowed in C# source, and C# doesn't permit Unicode in keywords, so the resulting syntax must be an identifier for a function called int. So we now have two functions called "int". The real heart of this question boils down to function overloading rules. Many people missed this part completely. Both methods will contribute to the set of candidate function members for possible overloading, as the integer literal '5' can be implicitly converted to both short and byte. The question is, which one?

Considering two conversion targets T1 and T2, T1 is a better conversion target than T2 if an implicit conversion from T1 to T2 exists, and no implicit conversion from T2 to T1 exists. Since one does exist from byte to short but not vice-versa, the method taking a byte is selected as the overload, giving an output of '4'.

Question 2


The answers to this question were rather intuitive once you realized that there was both a type and a variable named A, but it exposes an interesting part of the language. From the standard:
Quote:The grammar for a cast-expression leads to certain syntactic ambiguities. For example, the expression (x)-y could either be interpreted as a cast-expression (a cast of -y to type x) or as an additive-expression combined with a parenthesized-expression (which computes the value x - y).

For that reason, a rule was introduced that requires that for the expression to be considered a cast, the token immediately following the closing parenthesis must be an opening parenthesis or an identifier. Since in the case of (x)-y the immediate token is a '-', it resolves to an expression instead of a cast.

The output for this question is therefore -1 and then -5.

Question 3


A lot of people got tripped up on the assignment to this in this question. In a value type constructor, this is treated identically to an out parameter of the function, and is therefore legally assignable. In fact, you are required to do so in one form or another in order for a value type constructor to be legal. Usually though, code just assigns the individual members rather than the whole instance at once.

Moving on, we come to the behavior of static initialization. For all value types, the static field is first default initialized to all zeroes. The initializer is run at some implementation-defined time prior to the first use of that field. Therefore, we enter the Foo() constructor and assign 2 to the I field, and then proceed to assign the static field F to this instance. In either case, this will wipe out the assignment we just made, so the output should never be '2'. Once we access F, we are guaranteed that the initializer has run, so we will take on whatever value F currently has for I.

When the initializer for F runs, it calls into the Foo() constructor and assigns 5 to the I field. But then it goes and takes the value of F, which has been default initialized to all zeroes, and overwrites it. When the initializer completes, F has been initialized to all zeroes. Therefore, the output of the program is neither '2' nor '5', but '0'.

Question 4


This question is similar to Question 2 in that the output becomes easy to guess when you see the code in a simplified form like this, and also because it addresses another case of ambiguity in the C# specification that warranted explicit rules to resolve.

To resolve this, the parser looks at the token immediately proceeding the closing angle bracket '>'. If it's one of "( ) ] } : ; , . ? == !=" then it is evaluated as a type argument list (aka. a generic function), otherwise it is not, even if there is no other possible parse of the sequence of tokens. In the first case of our example, there is a '(' token proceeding the closing angle bracket, so it is parsed as a generic function call. In the second, there is a '-' operator, which is not in the above list and therefore results in an expression instead. The resulting output is therefore -7, False True.

Question 5


This is another question that relies on the rules of static initialization. Besides the rules mentioned previously for question 3, this question also relies on knowing that the initialization order for static fields is the order in which they are defined textually in the source file. Some people thought that the fields would be initialized in order of use, but this is not the case. Once again we rely on having the fields zero-initialized, and then a is initialized first to b (which is 0) + 1, giving it a value of one. Final output for this question is therefore a = 1, b = 2.

That's it for the quiz. I hope you learned something new from it.
Previous Entry C# Quiz
Next Entry PIX Managed x64
0 likes 1 comments

Comments

remigius
Quote:Original post by Mike.PopoloskiI hope you learned something new from it.


I learned I'm getting old, rusty and cranky [smile]

If you'd have given me a similar test in Java some 10 years ago, I'd have jumped on the chance of validating and expanding my knowledge and probably would have gotten most of them right. These days I seem to be content to stay away from edge cases and sticking to C# code that is as simple and unambiguous as possible. I even find myself adding parenthesis to conditionals which I know are redundant... my god, what have I become? :p

Someone should write a little quiz like this for HLSL sometime though. The edge cases there are are even more shady and you run into them much more frequently I think.
February 24, 2010 09:29 AM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement

Latest Entries

New Blog

2022 views

Progress Update

1550 views

Start of Project

1513 views

New Job

2220 views

The Downward Spiral

2879 views

Job Interviews

1480 views
Advertisement