C# INTERVIEW QUESTION TIPS PART 3

5. Run-time Type Information

5.1 How can I check the type of an object at runtime?

You can use the is keyword. For example:
using System;

class CApp
{
public static void Main()
{
string s = "fred";
long i = 10;

Console.WriteLine( "{0} is {1}an integer", s, (IsInteger(s) ? "" : "not ") );
Console.WriteLine( "{0} is {1}an integer", i, (IsInteger(i) ? "" : "not ") );
}
static bool IsInteger( object obj )
{
if( obj is int || obj is long )
return true;
else
return false;
}
}
produces the output:
fred is not an integer
10 is an integer
5.2 Can I get the name of a type at runtime?
Yes, use the GetType method of the object class (which all types inherit from). For example:
using System;

class CTest
{
class CApp
{
public static void Main()
{
long i = 10;
CTest ctest = new CTest();

DisplayTypeInfo( ctest );
DisplayTypeInfo( i );
}
static void DisplayTypeInfo( object obj )
{
Console.WriteLine( "Type name = {0}, full type name = {1}", obj.GetType(), obj.GetType().FullName );
}
}
}
produces the following output:
Type name = CTest, full type name = CTest
Type name = Int64, full type name = System.Int64

6. Miscellaneous

6.1 How do I do a case-insensitive string comparison?

Use the String.Compare function. Its third parameter is a boolean which specifies whether case should be ignored or not.
"fred" == "Fred" // false
System.String.Compare( "fred", "Fred", true ) // true

6.2 Does C# support a variable number of arguments?

Yes, using the params keyword. The arguments are specified as a list of arguments of a specific type, e.g. int. For ultimate flexibility, the type can be object. The standard example of a method which uses this approach is System.Console.WriteLine().

6.3 How can I process command-line arguments?

Like this:
using System;

class CApp
{
public static void Main( string[] args )
{
Console.WriteLine( "You passed the following arguments:" );
foreach( string arg in args )
Console.WriteLine( arg );
}
}

6.4 Does C# do array bounds checking?

Yes. An IndexOutOfRange exception is used to signal an error.

6.5 How can I make sure my C# classes will interoperate with other .NET languages?

Make sure your C# code conforms to the Common Language Subset (CLS). To help with this, add the [assembly:CLSCompliant(true)] global attribute to your C# source files. The compiler will emit an error if you use a C# feature which is not CLS-compliant.

6.6 How do I use the 'using' keyword with multiple objects?

You can nest using statements, like this:
using( obj1 )
{
using( obj2 )
{
...
}
}
However consider using this more aesthetically pleasing (but functionally identical) formatting:
using( obj1 )
using( obj2 )
{
...
}
6.7 What is the difference between == and object.Equals?

For value types, == and Equals() usually compare two objects by value. For example:
int x = 10;
int y = 10;
Console.WriteLine( x == y );
Console.WriteLine( x.Equals(y) );
will display:
True
True
However things are more complex for reference types. Generally speaking, for reference types == is expected to perform an identity comparison, i.e. it will only return true if both references point to the same object. By contrast, Equals() is expected to perform a value comparison, i.e. it will return true if the references point to objects that are equivalent. For example:
StringBuilder s1 = new StringBuilder("fred");
StringBuilder s2 = new StringBuilder("fred");
Console.WriteLine( s1 == s2 );
Console.WriteLine( s1.Equals(s2) );
will display:
False
True
s1 and s2 are different objects (hence == returns false), but they are equivalent (hence Equals() returns true).
Unfortunately there are exceptions to these rules. The implementation of Equals() in System.Object (the one you'll inherit by default if you write a class) compares identity, i.e. it's the same as operator==. So Equals() only tests for equivalence if the class author overrides the method (and implements it correctly). Another exception is the string class - its operator== compares value rather than identity.
Bottom line: If you want to perform an identity comparison use the ReferenceEquals() method. If you want to perform a value comparison, use Equals() but be aware that it will only work if the type has overridden the default implementation. Avoid operator== with reference types (except perhaps strings), as it's simply too ambiguous.
6.8 How do I enforce const correctness in C#?
You can't - at least not in the same way you do in C++. C# (actually, the CLI) has no real concept of const correctness, For example, there's no way to specify that a method should not modify an argument passed in to it. And there's no way to specify that a method does not modify the object on which it is acting.
To get a feel for the angst this causes among some C++ programmers, read the feedback on this post from Raymond Chen.
There are of course ways of addressing this issue. For example, see Brad Abram's post (and associated feedback) for some ideas on adding optional read-only behaviour to collection classes.

7. C# 2.0

7.1 What are the new features in C# 2.0?

Support for all of the new framework features such as generics, anonymous methods, partial classes, iterators and static classes. See the .NET FAQ for more on these features.
Delegate inference is a new feature of the C# compiler which makes delegate usage a little simpler. It allows you to write this:
Thread t = new Thread(ThreadFunc);
instead of this:
Thread t = new Thread( new ThreadStart(ThreadFunc) );
Another minor but welcome addition is the explicit global namespace, which fixes a hole in namespace usage in C# 1.x. You can prefix a type name with global:: to indicate that the type belongs to the global namespace, thus avoiding problems where the compiler infers the namespace and gets it wrong.
Finally C# 2.0 includes some syntactic sugar for the new System.Nullable type. You can use T? as a synonym for System.Nullable, where T is a value type. As suggested by the name, this allows values of the type to be 'null', or 'undefined'.