Click here to Skip to main content
Click here to Skip to main content

Quiz - C# and .NET Secrets

, 1 Feb 2008
Rate this:
Please Sign up or sign in to vote.
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!

Download DotNetQuizSamples.zip - 253.11 KB

Logo_small.png

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:

Question 1 - A Simple One To Start

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.

Question 2 - String vs. System.String

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!

internal class PersonString
{
    public string FirstName { get; private set; }
    public string LastName { get; private set; }

    public PersonString(string FirstName, string LastName)
    {
        this.FirstName = FirstName;
        this.LastName = LastName;
    }
    public void Replace( string TextToFind, string ReplacingText )
    {
        FirstName = FirstName.Replace( TextToFind, ReplacingText );
        LastName = LastName.Replace( TextToFind, ReplacingText );
    }
    public override string ToString()
    {
        return FirstName + " " + LastName;
    }
}
internal class PersonSystemString
{
    public System.String FirstName { get; private set; }
    public System.String LastName { get; private set; }

    public PersonSystemString(System.String FirstName, 
        System.String LastName)
    {
        this.FirstName = FirstName;
        this.LastName = LastName;
    }
    public void Replace(System.String TextToFind, 
        System.String ReplacingText)
    {
        FirstName = FirstName.Replace(TextToFind, ReplacingText);
        LastName = LastName.Replace(TextToFind, ReplacingText);
    }
    public override System.String ToString()
    {
        return FirstName + " " + LastName;
    }
}

The implementation of Main uses implicitly typed variables. This is a new featur of C# 3.0! See question 2 for more details about implicitly typed variables.

static class Program
{
    static void Main()
    {
        var pString = new PersonString("Rainer", "Stropek");
        System.Console.WriteLine(pString);

        var pSystemString = new PersonSystemString("Rainer", "Stropek");
        System.Console.WriteLine(pSystemString);
    }
}

After compiling the program we can use ILDASM (MS Intermediate Language Disassembler) to generate a readable version of the IL:

ildasm.exe /output="$(TargetDir)\$(TargetName).il" $(TargetPath)

If you compare the IL of the two classes you can see that they are (with the exception of their names) absolutely identical.

Question 3 - Implicitly Typed Variables

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?

namespace ImplicitTypes
{
    class Program
    {
        static void Main()
        {
            var v = "Hello World!";
            v = 10;
            System.Console.WriteLine(v);
        }
    }
}

The correct answer is No, you cannot compile this code.

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!

You can read more about implicitly typed local variables in MSDN.

Question 4 - Value vs. Reference Types

What is the output of the following program?

namespace ValueVsReferenceTypes
{
    class Program
    {
        static void Main()
        {
            var stringValue = "Hello World!";
            var stringValue2 = stringValue;
            stringValue = "Hello Austria!";
            System.Console.WriteLine(stringValue2);


            var array = new[] { 1, 2, 3, 4 };
            var array2 = array;
            array[0] = 99;
            System.Console.WriteLine(array2[0]);
        }
    }
}

The correct answer is Hello World! 99.

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].

Question 5 - Finalizing Objects

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.

Take a look at the following program:

using System;
using System.IO;

namespace Finalizers
{
    internal class FileGenerator : IDisposable
    {
        public FileGenerator()
        {
        }
        ~FileGenerator()
        {
            // Just a debug output
            Console.WriteLine("Closing file!");
        }
        public void Generate(int Length)
        {
            // Here some work is done...
        }
        public void Dispose()
        {
            // Just a debug output
            Console.WriteLine("Disposing object!");
        }
    }

    class Program
    {
        static void Generate()
        {
            using ( var fGen = new FileGenerator() )
                fGen.Generate(512);
        }
        static void Main(string[] args)
        {
            Generate();
            // Here we do some work; simulated by ReadLine statement
            Console.Write("Please Press Enter...");
            Console.ReadLine();
        }
    }
}

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:

  1. Try to avoid objects that require clean up!
  2. If you cannot avoid it provide a destructor or a finalizer.
  3. Add an additional method with which a user can force the object to clean up.
    1. Implement the IDisposable interface by providing a Dispose-method. Follow the guidelines for implementing IDisposable that are included in MSDN.
    2. 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.
    3. Do not forget to call SuppressFinalize in your Dispose-method. Otherwise you would waste performance.
  4. Objects that implement IDisposable should be used inside C# using statement. It automatically cleans up correctly.

Jeffrey Richter wrote an interesting article about memory management and finalization of objects in the MSDN Magazine. Although the text has been written in 2000 it is still worth reading!

Question 6 - Lambda Expressions

In C# every method must have a name. True or false?

That's not true! Since the version 2.0 C# has known anonymous methods. Take a look at the following code:

namespace AnonymousMethods
{
    class Program
    {
        delegate int CalcOperation(int x);
        static int PerformCalculation( int x, CalcOperation calc )
        {
            return calc(x);
        }
        static void Main()
        {
            System.Console.Write(PerformCalculation(5, 
                delegate(int x) { return x * x; }));
        }
    }
}

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:

static void Main()
{
    System.Console.Write(PerformCalculation(5, x => x*x ));
}

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.

Question 7 - Nullable Types

What is the output of the following program?

namespace NullableTypes
{
    class Program
    {
        static void Main()
        {
            int a = 10;
            int? b = 20;
            int? c = null;
            System.Console.WriteLine( a + c ?? b );
        }
    }
}

The correct answer is 20.

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.

Question 8 - JIT Compiler

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:

namespace JIT
{
    class Program
    {
        static void Method1()
        {
            System.Console.WriteLine("Method1");
        }
        static void Method2()
        {
            System.Console.WriteLine("Method2");
        }
        static void Main()
        {
            System.Console.ReadLine();
            Method1();
            System.Console.ReadLine();
            Method2();
            System.Console.ReadLine();
            Method1();
            System.Console.ReadLine();
        }
    }
}

JIT_large.png

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.

Note: You cannot use ngen with ASP.NET (for details see Microsoft Support Site).

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

r.stropek
software architects
Austria Austria
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.

Comments and Discussions

 
GeneralMy vote of 5 Pinmemberandoniu14-Oct-10 3:11 
GeneralAnswer for Question 7 is "The program does not compile". PinmemberTerry Liew28-Jun-10 23:47 
GeneralRe: Answer for Question 7 is "The program does not compile". Pinmembersepehr10147-Aug-11 22:55 
GeneralJus some comments... PinmemberOleg Shilo5-Feb-08 14:14 
GeneralNice quiz Pinmembersi6185-Feb-08 13:41 
GeneralGood test of general skills PinmemberRobert Royall1-Feb-08 7:46 
GeneralInteresting Pinmembermerlin9811-Feb-08 5:36 
GeneralDoesn't look like a secret... PinmemberZaur Nasibov31-Jan-08 22:15 
GeneralRe: Doesn't look like a secret... Pinmemberr.stropek1-Feb-08 3:54 
GeneralOne minor quibble PinmemberPIEBALDconsult31-Jan-08 15:21 
GeneralRe: One minor quibble Pinmemberr.stropek1-Feb-08 3:51 
GeneralI think they are easy PinmemberDenisSavenkov31-Jan-08 12:13 
GeneralRe: I think they are easy PinmemberRealDex31-Jan-08 21:13 
GeneralRe: I think they are easy Pinmemberr.stropek1-Feb-08 3:36 
GeneralNice job and one suggestion Pinmembergregsohl31-Jan-08 11:50 
GeneralRe: Nice job and one suggestion Pinmemberr.stropek1-Feb-08 3:56 
GeneralRe: Nice job and one suggestion Pinmembersergueis5-Feb-08 16:20 
GeneralCool PinmemberBen Daniel31-Jan-08 11:27 
GeneralRe: Cool Pinmemberr.stropek1-Feb-08 3:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 1 Feb 2008
Article Copyright 2008 by r.stropek
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid