C4Swimmers Newsletter  

(FAQ) C# Frequently Asked Questions Page4

FAQ: C# Frequently Asked Questions Page4


Why aren't reference types polymorphic?

Q: Why aren't reference types polymorphic?

A: Consider the following code:

using System;
class Dog {
public string Name;
}

class Test
{
public static void Swap(ref object a, ref object b) {
object temp;
temp = a;
a = b;
b = temp;
} public static void Main() { Dog d1 = new Dog(); d1.Name = "fido"; Dog d2 = new Dog(); d2.Name = "rex"; Swap(ref d1, ref d2); } }


The compiler will report an error on the call to the Swap() function. Why? Consider if the swap function was like this:

public static void Swap(ref object a, ref object b) {

a = 5;

b = “Hello“;

}

If the compiler allowed this code, it would mean assigning a boxed int to a Dog object, which is clearly not type safe.

When should I use == and when should I use Equals?

The Equals method is just a virtual one defined in System.Object, and overridden by whichever classes choose to do so. The == operator is an operator which can be overloaded by classes, but which usually has identity behaviour.

For reference types where == has not been overloaded, it compares whether two references refer to the same object - which is exactly what the implementation of Equals does in System.Object.

Value types do not provide an overload for == by default. However, most of the value types provided by the framework provide their own overload. The default implementation of Equals for a value type is provided by ValueType, and uses reflection to make the comparison, which makes it significantly slower than a type-specific implementation normally would be. This implementation also calls Equals on pairs of references within the two values being compared.

However, the main difference between the two types of comparison in normal use (where you're unlikely to be defining your own value types very often) is polymorphism. Operators are overloaded, not overridden, which means that unless the compiler knows to call the more specific version, it'll just call the identity version. To illustrate that, here's an example:

using System;

public class Test
{
static void Main()
{
// Create two equal but distinct strings
string a = new string(new char[] {'h', 'e', 'l', 'l', 'o'});
string b = new string(new char[] {'h', 'e', 'l', 'l', 'o'});

Console.WriteLine (a==b);
Console.WriteLine (a.Equals(b));

// Now let's see what happens with the same tests but
// with variables of type object
object c = a;
object d = b;

Console.WriteLine (c==d);
Console.WriteLine (c.Equals(d));
}
}

The results are:

True
True
False
True

The third line is False because the compiler can only call the non-overloaded version of == as it doesn't know that the contents of c and d are both string references. As they are references to different strings, the identity operator returns false.

So, when should you use which operator? My rule of thumb is that for almost all reference types, use Equals when you want to test equality rather than reference identity. The exception is for strings - comparing strings with == does make things an awful lot simpler and more readable but you need to remember that both sides of the operator must be expressions of type string in order to get the comparison to work properly.

For value types, I'd normally use == for easier-to-read code. Things would get tricky if a value type provided an overload for == which acted differently to Equals, but I'd consider such a type very badly designed to start with.

Should I assign null to my local variables?

Q: Should I assign null to my local variables after I use them?

For example:

string s = ...;
Console.WriteLine(s);
s = null;

A: There is rarely a need to do this for local variables in C#

The lifetime of variables is tracked by the JIT - it analyzes how variables are used in a routine, and it knows exactly when the variable is no longer needed, and after that point, the value is available to be collected.

Interestingly, if you assign it to null, you are actually extending the lifetime of the variable slightly, so it could cause it to be garbage collected later (though realistically, there's unlikely to be any real difference here.

This is true for the vast majority of methods. If you have a method where your code lives for a while - a loop on a separate thread, for example - then it may be worthwhile to see if there are any unnecessary values living in variables while you wait.

Why do I need a null test before I invoke a delegate?

Q: Why do I need a null test before I invoke a delegate?

A: If you have an event in a class, you need to add a null test before you call the delegate. Typically, you would write:

if (Click != null)
Click(arg1, arg2);

There is actually a possible race condition here - the event can be cleared between the first and second line. You would actually want to write:

ClickHandler handler = Click;

if (handler != null)
handler(arg1, arg2);

usually. You might want to do some other sort of synchronization in other scenarios.

So back to the main question. Why is the null test required?

We can't change the existing behavior of calling through a delegate as some apps may depend on it, so it would have to be an addition to the language.

We have talked about adding an Invoke() keyword to the language to make this easier, but after a fair bit of discussion, we decided that we couldn't do the right thing all the time, so we elected not to do anything.

Why doesn't C# warn about unused methods?

Q: Why doesn't C# warn on unused methods?

A: This is something that the C# compiler could do, subject to a few caveats:

* Virtual functions would have to be excluded
* Interface implementations wouldn't have to be excluded
* You would get false positives if you used reflection
* You might get false positives if you used delegates (the compiler might be able to be smart here)

Other than that, it would be possible for us to do this, and we may do it in a future version.

How can I update my user interface from a thread that did not create it?

When performing any action on a control which requires the updating of a user interface element (e.g. setting the Text property on almost any class derived from Control, updating the data source behind a DataGrid), these operations MUST take place on the thread that created the UI element.

In order to do this, the Control class provides the Invoke method, which will take a delegate and execute it on the thread that the UI element was created on. In order to use this, one must declare a function that performs the UI operation. For example, say a form has a TextBox on it named m_TextBox. To update the text from another thread, create a method that will update the Text property on the TextBox:

// The declaration of the textbox.
private TextBox m_TextBox;

// Updates the textbox text.
private void UpdateText(string text)
{
// Set the textbox text.
m_TextBox.Text = text;
}

Now, create a delegate that has the same signature as the method that was previously defined:

public delegate void UpdateTextCallback(string text);

In your thread, you can call the Invoke method on m_TextBox, passing the delegate to call, as well as the parameters.

m_TextBox.Invoke(new UpdateTextCallback(this.UpdateText), 
new object[]{”Text generated on non-UI thread.”});

Note: Do not create a method that matches the EventHandler delegate signature and pass that. The implementation of Invoke on the Control class will not take into account the parameters passed to Invoke if the type of the delegate is EventHandler. It will pass the control that Invoke was called on for the sender parameter as well as the value returned by EventArgs.Empty for the e parameter.

Why can't I have static and instance methods with the same name?

Q: Why can't I have static and instance methods with the same name?

class Test
{
static void Process();
void Process();
void AmbiguousCaller() { Process(); }
}

there's no ambiguity, since the first can only be called through the type name, and the second can only be called through an instance.

A: It is true that there would be no ambiguity between the two functions as far as a compiler is concerned. There would, however, be a considerable potential for confusion on the part of the user. It would be tough to find the right method in documentation, and once you did, hard to be sure that you are calling the right version (ie you could accidentally call the static version when you wanted the instance version).

We therefore prohibit this case.

Where can I find sample C# code for simple threading?

Refer to the System.Threading namespace on MSDN for full details. Meanwhile here is a quick taste.

using System; 
using System.Threading; 

class ThreadTest 

public void Runme() 

Console.WriteLine("Runme Called"); 
Thread.Sleep(10000); 
}

public static void Main(String[] args)

ThreadTest b = new ThreadTest(); 
Thread t = new Thread(new ThreadStart(b.Runme)); 
t.Start(); 

Console.WriteLine("Thread 't' started.");
Console.WriteLine("There is no telling when " + 
"'Runme' will be invoked. "); 

t.Join(); 

Console.WriteLine("Thread 't' has ended."); 
}
}

How do C# generics compare to C++ templates?

Q: How do C# generics compare to C++ templates?

A: This is really a fairly complex topic. Anders has touched on it in an interview. I should state at the outset that the goals of generics are not the same as the goals of templates. There are some things that templates do better than generics, and vice versa.

Model

C++ templates use a compile-time model. When a template is used in a C++ program, the effect is as if a sophisticated macro processor had been used.

C# generics are not just a feature of the compiler, but also a feature of the runtime. A generic type such as List<T> maintains its generic-ness (genericity) after it has been compiled. Or, to look at it another way, the substitution that the C++ compiler does at compile time is done at JIT time in the C# generic world.

Error Checking

Error is best illustrated through an example. Consider a template that has a method like this;

T Add(T t1, Tt2)
{
return t1 + t2;
}

the C++ compiler will be able to parse this method successfully. When this template is actually used, the Ts will be replaced with an actual type. If a type such as int is used, the compiler will be able to create the Add method correctly, as it knows how to add two ints.

If a type such as Employee was used, the compiler would issue an error, as the compiler would know that there was no way to add two Employees.

The generics world is very different. Because the type that is used with the generic is not known at compile time, the compiler needs additional information about the type that will be used with a generic class.

This is done through constraints, which allow the author to constrain the types that can be used with a generic type.

For example:

Class List<T> where T:IComparable

means that whenever I use a T in my implementation, I can call the CompareTo() function on it.

Constraints could theoretically provide nearly the same level of flexibility that templates do, but that would require a very complex constraint syntax. For the Whidbey release, only certain operations can be specified through contraints, which limits the number of operations you can perform.

For example, there is no way to say that a generic type must have an add operator, so you can't write “a + b“ in a generic class.

It is possible to work around this at runtime using reflection, but the implementation isn't as clean and there may be a performance loss. We may address some of these issues in future releases

Run-time operations

Generics in C# have full run-time support. If you use reflection, you will find that you can reflect over generic types, and create them at runtime. There's no real analog of this in the C++ world.

Space Use

The use of space is different between C++ and C#. Because C++ templates are done at compile time, each use of a different type in a template results in a separate chunk of code being created by the compiler.

In the C# world, it's somewhat different. The actual implementations using a specific type are created at runtime. When the runtime creates a type like List<int>, the JIT will see if that has already been created. If it has, it merely users that code. If not, it will take the IL that the compiler generated and do appropriate replacements with the actual type.

That's not quite correct. There is a separate native code path for every value type, but since reference types are all reference-sized, they can share their implementation.

This means that the C# approach should have a smaller footprint on disk, and in memory, so that's an advantage for generics over C++ templates.

In fact, the C++ linker implements a feature known as “template folding“, where the linker looks for native code sections that are identical, and if it finds them, folds them together. So it's not a clear-cut as it would seem to be.

Template metaprogramming

C++ templates are sometimes used for a technique known as template metaprogramming. There is no way to do this in C#.

Where can I get a full comparison between C# and VB.NET?

Microsoft provides a very full language equivalents page which compares not only C# and VB.NET, but also other languages targeted at the .NET framework. It looks at the equivalent concepts, keywords, types, operators etc. A very valuable resource when you're trying to read or write code in a language which isn't your preferred one.

Is there an equivalent of MyClass?

No, C# doesn't have an equivalent of VB.NET's MyClass keyword. If you want to guarantee not to call an overridden version of a method, you need to make it non-virtual in the first place.

What do I use instead of addressof?

To create delegate instances in C#, you just specify the delegate type, the method, and (if you want to create a delegate targetting a different instance or type from the current one) the target. For instance, each of these creates a ThreadStart delegate:

ThreadStart x1 = new ThreadStart(SomeInstanceMethod);
ThreadStart x2 = new ThreadStart(AnotherType.SomeStaticMethod);
ThreadStart x3 = new ThreadStart(someVariable.SomeInstanceMethod);

How do I get the rightmost part of a string, as with the VB Right function?

Use String.Substring. Assuming that x is a string of length at least n, to get the last n characters, you would use x.Substring(x.Length-n).

Note that the above assumes that the string is at least n characters long. For a more robust version, you might use something like: x.Length < n ? x.Substring(x.Length-n) : x.

What are the equivalents of Me and MyBase?

Me in C# is this, and MyBase in C# is base. To access normal members, just use this.memberName or base.memberName. For information about chaining constructors together, see my article on constructors.

What's the equivalent of Nothing?

For reference types, the equivalent of VB's Nothing is C#'s null. For value types, it's the default value - 0, false, etc.

 

Next  Previous