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.