Casts using “as” (Pitfalls and Best Practices to Prevent Them #5)

Well – “as” is faster to type than a “real” cast using two brackets and has the same result. Really?

C# provides several ways to cast one type to another one. The two used in most cases are the “([Targettype]) [Variable]” and the “[Variable] as [Targettype]” notations. Many developers see them as equivalents, some even prefer “as” because it does not throw an exception when the cast fails.

Example

Let’s say we have a variable called obj of type Object and we want to cast it to an IFoo so we can call IFoo.Bar:

object obj;
//...
(obj as IFoo).Bar();

Read the rest of this entry »

Advertisements

Pitfalls and Best Practices to prevent them #3: this and base

“I use base to make clear that I am calling a inherited member” – why you shouldn’t.

You all know them: The keywords this and base.

Did you ever think about which of them you should use when you can use both?

Read the rest of this entry »

Pitfalls and Best Practices to prevent them #1: Order of the elements when iterating through a collection using foreach

Example

List<string> list = //Fill it;
//...
int index = 0;
foreach (string s in list)
    Console.WriteLine("Item \"{0}\" - Index: {1}", s, index++);

What does it do?

The example is kept quite simple: A generic List<string> gets filled with some items (—> Comment).

Later, all items in it and their indices are written to the Console.

Note: The foreach loop internally uses IEnumerable.GetEnumerator / IEnumerable<T>.GetEnumerator.

Doku says

MSDN (IEnumerator.GetEnumerator)

Initially, the enumerator is positioned before the first element in the collection. […] Therefore, you must call the MoveNext method to advance the enumerator to the first element of the collection before reading the value of Current.

[…] MoveNext sets Current to the next element.

If MoveNext passes the end of the collection, the enumerator is positioned after the last element in the collection and MoveNext returns false. […]

C# Language Specification (8.8.4: The foreach statement)

The order in which foreach traverses the elements of an array, is as follows: For single-dimensional arrays elements are traversed in increasing index order, starting with index 0 and ending with index Length – 1. For multi-dimensional arrays, elements are traversed such that the indices of the rightmost dimension are increased first, then the next left dimension, and so on to the left.

Problem

Well, it’s a question of interpretation: Does MoveNext set to the next element in the collection or only to the next element (regardless to its position in the collection)? Only the behavior when dealing with arrays is specified unambiguously.

There could be a class implementing (for whatever the reason) GetEnumerator like follows:

private List<string> innerList;
//...
public IEnumerator GetEnumerator()
{
    for (int i = this.innerList.Count - 1; i >= 0; i--)
        yield return this.innerList[i];
}

Using this code together with the first one causes significant problems: The displayed indices are wrong now.

And there are classes that behave different; Class" href="http://msdn.microsoft.com/en-us/library/xfhwa508.aspx" target=_blank>Dictionary<,> is a prime example:

For purposes of enumeration, each item in the dictionary is treated as a KeyValuePair<TKey, TValue> structure representing a value and its key. The order in which the items are returned is undefined.

How to solve?

Don’t use foreach loops when you need the index of an element. (And also don’t use IndexOf in a foreach loop – this, however, has performance reasons).

Use a plain old for-loop instead 😉

List<string> list = //Fill it;
//...
int index = 0;
for (int index = 0; index < list.Count; index++)
{
    string s = list[index]; //Of course you don't have to introduce a variable
    Console.WriteLine("Item \"{0}\" - Index: {1}", s, index++);
}

However, this is no solution if you are using a dictionary; thanks to SeeQuark for informing me about this. In this case, if you really need a well-definied order, you’ll have to add an index to the elements in it.

Generalization / Best Practise:

Do not rely on the order elements will be returned by an iterator. As the foreach-loop uses one, the same applies to it. Foreach-loops using a counter variable in order to determine the index of each element should be replaced with for-loops.

DotNetKicks Image

New column: Pitfalls and Best Practices to prevent them

As you maybe know I am an active member of myCSharp.de.

Reading through the postings there (and answering them, of course ;-)) I sometimes think that there definitely have to be other people with the same problem without knowing it.

That means those problems are really hidden logical mistakes which are mainly caused by inaccurate usage of types or language features. In most cases they won’t catch somebody’s eye as their impacts only come to light under special (unfortunate) circumstances. Then, however, they are really difficult to find. You could say: They are no real bugs but they may cause bugs.

So I decided to start this new column which I’ll try to keep alive as long as this blog will exist. I hope, you’ll like it. 🙂

DotNetKicks Image
Posted in Pitfalls. Tags: , , , . Comments Off on New column: Pitfalls and Best Practices to prevent them