Sunny Ahuwanya's Blog

Mostly notes on .NET and C#

C# Brainteasers Part I

Every now and then, I pick up C# Precisely by Peter Sestoft and Henrik I. Hansen, a great C# reference book that should be recommended more often.
Every time I read the text, I find bemusingly odd but very correct C# code examples.

Here are some C# brainteasers I've compiled from the book. The answers are at the end of this post.

1. What does the following code display?

class Concat
{
    static void Main()
    {
        Console.WriteLine(20 + 45 + "A");
        Console.WriteLine("A" + 20 + 45);
    }
}

Okay, that one was easy -- how about the rest?

2. What is wrong with this code?

class One
{
    sealed void SealedOnly()
    {
        // Do something
    }
    
    virtual void Virt()
    {
        // Do something
    }
}

3. What is wrong with this code?

class BaseClass
{
    public BaseClass (string Arg0)
    {
        //Do stuff       
    }
}

class DerivedClass : BaseClass 
{
    //Do more stuff
}

4. What is wrong with this code?


class Student
{
    public Student (string Name) 
    {
        //Call other constructor
        this.Student(Name, null);
    }

    public Student (string Name, DateTime? DateEnrolled)
    {
        this.name = Name;
        this.dateEnrolled = DateEnrolled;       
    }

    private string name;
    private DateTime? dateEnrolled;

}

5. What is the class access modifier for class A? how about class B?

class A
{
    class B
    {

    }
}


Answers:

1.
The code will display:

65A
A2045

This is because the + operator is left associative.


2.
The code will not compile because of errors (shown in comments) below.

class One
{
    sealed void SealedOnly() //error CS0238: Cannot be sealed because it is not an override 
    {
         // Do something
    }

    virtual void Virt() //error CS0621: virtual or abstract members cannot be private
    {
       // Do something
    }
}

You can’t have a sealed method that does not override a base method.
You can’t have a virtual or abstract method with a private access modifier.


3.
The code will not compile because of the error (shown in the comment) below.
class BaseClass
{
    public BaseClass (string Arg0)
    {
        //Do stuff       
    }
}

class DerivedClass : BaseClass // error CS1501: No overload for method 'BaseClass' takes '0' arguments (DerivedClass must explicitly call BaseClass constructor because there is no parameterless base constructor)
{
    //Do more stuff
}
This one is a bit tricky to explain. The C# compiler generates a parameterless constructor for concrete classes without any defined constructors. If there was no constructor defined for the base class, then the C# compiler will generate a parameterless constructor.
A parameterless constructor will also be generated for the derived class (since it doesn’t have any constructors) which will override the parameterless constructor for the base class.

In this case, a constructor with a single parameter was defined for the base class, so the C# compiler will NOT generate a parameterless constructor for the base class. The derived class however will have a parameterless constructor generated. The problem with the code snippet above is that the derived class’s parameterless constructor can not find a base parameterless constructor to override.

To resolve this issue, you can add a parameterless constructor to the base class, add a constructor with the same signature as the one in the base class to the derived class, or add a parameterless constructor to the the derived class with this declaration:
public DerivedClass(): base("")
{
}
This creates a parameterless constructor for the derived class which calls the base class constructor


4.
The code will not compile because of the error (shown in the comment) below.
    class Student
    {
        public Student(string Name) 
        {
            this.Student(Name, null); // error CS0117: 'Student' does not contain a definition for 'Student'
        }

        public Student(string Name, DateTime? DateEnrolled)
        {
            this.name = Name;
            this.dateEnrolled = DateEnrolled;
        }

        private string name;
        private DateTime? dateEnrolled;

    }
You cannot call constructor code using regular method access syntax, even from another constructor.
To call another constructor, use this syntax:
public Student(string Name) : this(Name, null)
{
}

5.
 A - internal
 B - private
Top-level classes without a class access modifier default to internal (and can only be either public or internal).
Nested classes without a class access modifier default to private.