Quiz - C# and .NET Secrets

You are a .NET professional? C# is your native language? Try to answer these questions and prove it! We have assembled a set of questions around C#, the CLR and Intermediate Language. Even if you are not perfectly familiar with those topics give it a try!

Introduction

software architects invites you to prove your knowledge about certain subjects concerning Microsoft .NET technology by participating in a monthly quiz. This month the quiz is about C# and .NET secrets. In this article you can reread the questions. Additionally you get background information about the correct answers.

You haven't participated in the quiz yet? Try it first and come back to read about the answers later!

Here is a list of all questions included in the quiz. Use the hyperlinks to jump to the topic you are interested in:

The CTS (Common Type System) does not know about object orientation at all. Programming languages like C# include all the OO logic. They generate procedural IL code behind the scenes. True or false?

That's absolutely not true! The Common Type System supports object oriented and procedural languages. It has support for OO constructs built in.

If you are interested you can download the ECMA C# and Common Language Infrastructure Standards from Microsoft's website. The documents include a good introduction into as well as a detailed documentation of the Common Type System.

What is more efficient in respect of memory usage and performance: The use of string or the use of System.String?

The correct answer is It doesn’t matter which one you take, they perform equally. string is a synonym for System.String. Therefore it does not matter if you take string or System.String.

You can prove that the C# compiler and the .NET CLR treats string and System.String equally by looking at the generated code in intermediate language. Take a look at the following lines of code. As you can see we define two classes handling strings. One of them (PersonString) uses string to do its job; the other (PersonSystemString) uses System.String.

Mark the use of auto-implemented properties in this sample. This is a new feature of C# 3.0!

C# 3.0 introduces implicitly typed local variables. You do not need to specify a type for a local variable any more! The compiler figures out which type to use for you. So what do you think; does the following code work?

The code does not compile. The line v = 10; produces the error Cannot implicitly convert type 'int' to 'string'. The reason is that the new keyword var does not mean variant! It just means that the compiler determines and assigns the most appropriate type during compile time!

Although System.String is a class and therefore a reference type you can never change the content of a string. The type is called immutable (read-only) because its value cannot be modified once it has been created. Every modification to a string variable generates a new String object. Therefore the assignment of "Hello Austria!" to stringValue does not affect the value of stringValue2.

System.Array behaves differently. If you assign an array to another variable only a new reference to the array is generated. A modification of an array element is visible to everyone holding a reference to the array. Knowing this it should be clear to you why array2[0] contains 99 even if this value has been assigned to array[0].

It is a good practise to use destructors in C# just like in C++. Put cleanup code in your class' destructor and the CLR will care for the rest. Is that correct?

The correct answer is Cleaning up in the destructor is fine. But that is not enough!

C# knows destructors. A destructor is the same as a Finalize-Method in which you call base.Finalize(); at the end. However, using finalizers costs performance. Additionally you have to be aware that finalizers are not called when an object is no longer needed by your program. It is called when the garbage collector decides to remove the object. Usually you cannot predict when that will happen. Therefore you have to do a little bit more to provide a proper cleanup mechanism in your programs.

If you run this program you will notice that the output Closing file! appears at the very end of the program. The destructor is not immediately called when the object fGen is out of scope. The CLR calls it when the garbage collector frees the object.

This is one of the reasons why a destructor or a finalizer is not enough for an object that has to clean up when it is no longer needed. Here is a list of things you should consider regarding cleanup:

Try to avoid objects that require clean up!

If you cannot avoid it provide a destructor or a finalizer.

Add an additional method with which a user can force the object to clean up.

Implement the IDisposable interface by providing a Dispose-method. Follow the guidelines for implementing IDisposable that are included in MSDN.

If a user can (re)open the object using some kind of Open-method offer a Close-method in addition to Dispose. The Close-method should call Dispose internally.

Do not forget to call SuppressFinalize in your Dispose-method. Otherwise you would waste performance.

Objects that implement IDisposable should be used inside C# using statement. It automatically cleans up correctly.

The main-method creates an anonymous method that is passed in the calc-parameter to the PerformCalculation-method. This construct is quite useful in a situation when having to create a method might seem an unnecessary overhead.

In C# 3.0 you can replace anonymous methods with Lamdba Expressions in most cases. In our case we could change the implementation of the Main-method as follows:

If you take a look behind the scenes and check the intermediate language that the C# compiler generates you will see that the generated IL nearly does not differ between C# 2.0 anonymous methods and Lamdba Expressions.

In C# you can make every value type nullable by adding a question mark to the type's name (you could also use System.Nullable<T> instead of the ?). The operator ?? can be used to specify a default value for an expression. This default value is returned if the expression evaluates to null. In our case c is null; therefore a + c is null and the default value b (20) is returned.

The JIT compiler converts the IL in a portable executable into native machine language...

The correct answer is ...method by method.

During loading the CLR creates a stub for each method in a type when it is loaded and initialized. When a method is called for the first time the stub passes control to the JIT compiler which converts the MSIL for that method into native code. If the method is called again the native code is executed without involving the JIT.

You can observe how the JITter generates native code using the following code sample:

In the Performance Monitor you can see how the JITter generates native code.

If you do not want to convert your IL code method by method every time the program starts you can use the Native Image Generator (ngen.exe) to convert it e.g. during installation. ngen generates processor-specific machine code in the native image cache. The runtime uses these images from the cache instead of using the JIT compiler to compile the original assembly.

Share

About the Author

Hi, my name is Rainer Stropek. I am living a small city named Traun in Austria. Since 1993 I have worked as a developer and IT consultant focusing on building database oriented solutions. After being a freelancer for more than six years I founded a small IT consulting company together with some partners in 1999. In 2007 my friend Karin and I decided that we wanted to build a business based on COTS (component off-the-shelf) software. As a result we founded "software architects" and developed the time tracking software "time cockpit" (http://www.timecockpit.com). If you want to know more about our companies check out my blogs at http://www.software-architects.com and http://www.timecockpit.com or take a look at my profile in XING (http://www.openbc.com/hp/Rainer_Stropek2/).

I graduated the Higher Technical School for MIS at Leonding (A) in 1993. After that I started to study MIS at the Johannes Kepler University Linz (A). Unfortunately I had to stop my study because at that time it was incompatible with my work. In 2005 I finally finished my BSc (Hons) in Computing at the University of Derby (UK). Currently I focus on IT consulting, development, training and giving speeches in the area of .NET and WPF, SQL Server and Data Warehousing.

It is good to have questions, which require not obvious answers, summarised like that.

Though I have a few comments if you do not mind.

Question 4 - Value vs. Reference TypesYou are using string and array (both are reference types) to demonstrate differences between value and reference types only because string in your example behave like a value type. This seems to be a strange choice. Why not to use some struct and array?

I do appreciate that string is an immutable type (you mentioned this too) however this fact should not be discussed in under the topic "Value vs. Reference Types" but rather in properly named paragraph.

Question 4 - String vs. System.StringThere is nothing wrong with your answer but I think the sentence "string is a synonym for System.String" is a bit misleading.

You see it is the same at to say that "Iron Lady" is a synonym for Margaret Thatcher. Well, it is not, it is just another name for the real person. The same with strings: the type actual name is System.String and it is known in C# world as string. However in other CLR languages it can be known as System::String or even as something else (e.g. str). Of course this is minor but I would rephrase your sentence as following: "string is an alias for System.String.

This was a great idea! I love quizzes like this, it gives me a chance to dredge up old knowledge I've had packed away inside my brain.

For anyone who's interested, here's a little more in-depth overview of the subject matter:

Q2: Nearly all the native C# primitive value types are synonyms. string, int, long, byte, etc. are all synonyms of their CLR counterparts (i.e. System.String, System.Int32, System.Int64, and System.Byte). I believe I heard somewhere that the synonyms are to more closely match the declaration environment of C/C++/Java.

Q7: The "??" operator is formally known as "Null-Coalesce". (Just threw that out there so people can Google it easier.)

Q8: NGEN doesn't work on ASP.NET because the runtime compiles pages the first time they are requested. The compiled page is cached and used until you make a change to the source code (or if you deploy a new IL compiled assembly). Then the page is recompiled. The reason for this is so it doesn't interrupt access to the pages; if you request a page, then I change it, your page still posts back to the server correctly because ASP.NET still has it in the cache. When you request the page again, only then you get the new updated page. That's also why it takes so long to start an ASP.NET site when you debug it - it's compiling the page in the background first.

The corresponding data type for "System.String" in the Common Type System (CTS) is called "string". The IL also contains the keyword "string" wherever you use "System.String" in C#.

Because of your comment I looked up the exact definition of the type "string" in the C# reference manual. You are right! There they write that "string" is a synonym for "String". Because of the IL generated from C# code I really thought it must be the other way round. However, I am sure the guys who wrote the C# manual knows it better than me -> I will fix the question in the quiz.

If you got everything correct you are a REAL C# professional in my view! I tried to integrate some questions about new C# features introduced in 3.0 and I hope that even experienced programmers who maybe haven't looked at C# 3 by now can benefit from those answers.

Got most of them right! lol Just wasn't aware of the ?? operator which is very handy! And didn't know that the JIT compiler compiled methods as needed - I thought for sure it would have compiled the entire app when started. Also never used the performance monitor so was impressed by all the things that could be measured.

If I got them all right I was going to flame you that even an amateur like me could get this quiz right lol, but you surprised me in the end and I ended up learning a couple cool new things! Thanks.