Jan 27

C# Sucks: Excessively Strict Typing

So my first gripe about C# is one that I ran into by mistake. I was playing around with some AJAX components, and one called for a web service method that returned an array of strings. I wanted to populate that array of strings with a database call. That seems simple enough, right?

Wrong. It took me several hours to figure out what object types were being returned by methods, what object types I wanted to be returned by methods, and what in G-d’s name I needed to do to get the values from the one type to the other.

Eventually I managed to extract the strings I wanted from the jumble of overlapping database classes and methods (why a framework needs that many ways to get data from a database, I don’t know). Now all I had to do was stuff those strings into an array. That seems simple enough, right?

Wrong. C# doesn’t allow for dynamically sized arrays. OK, well, I just need to find the size of the data set and make the array that size. Except I can’t just get the size of the data set. Why? Because for some reason the database select method I stumbled on returns an IEnumerable, which for some reason doesn’t keep a count of its members. Because why would you ever need to know how many results you get from a query without wanting to first loop over those results?

So putting that data directly into an array would mean looping over the data set not once, but twice. The first time around I’d only be incrementing a counter. Then I could initialize my array to the correct size. Then I could loop over the data set again and actually populate the array. Seriously, Microsoft?

I couldn’t bring myself to do that, so I did some quick searching and found the ArrayList class. It was exactly what I wanted, and it had a seemingly straightforward method to convert its contents into an array. Hooray.

So I try something like the following code:

public string[] someFunction(string someArg) {
	ArrayList aList = new ArrayList();
	// Populate aList with string objects
	return aList.ToArray();
}

No good. It throws an error saying I cannot implicitly convert an array of objects into an array of strings. I think it’s odd that this is an issue given that the objects are strings, but I try the following:

public string[] someFunction(string someArg) {
	ArrayList aList = new ArrayList();
	// Populate aList with string objects
	return (string[]) aList.ToArray();
}

This doesn’t give me any errors, but it doesn’t give me any data, either. Fine. If that’s how you want to play it, C#, that’s how we’ll play it. So I try this:

public string[] someFunction(string someArg) {
	ArrayList aList = new ArrayList();
	// Populate aList with string objects
	return aList.ToArray(typeof(string));
}

Suddenly the angry red squiggly is back, with the error that I cannot implicitly convert type ‘System.Array’ to type ‘string[]‘. It assures me that an explicit conversion exists, and asks me if I’m missing a cast. You’re joking, right? Right?

As it turns out, what I actually needed was:

public string[] someFunction(string someArg) {
	ArrayList aList = new ArrayList();
	// Populate aList with string objects
	return (string[]) aList.ToArray(typeof(string));
}

Because it’s not enough to convert a list of string objects to an array of string objects. You also need to convert the individual string objects to string objects. And then you also need to convert the array of string objects to an array of string objects. Did you notice that only one of those steps actually changed the type of anything? I certainly did.

Maybe this wouldn’t have been such an issue if I hadn’t been using a pre-built component that demanded an actual array of strings. Perhaps “old school” arrays are used infrequently in the rest of C# land. But the fact remains that a language should not require you to cast a type into itself. Repeatedly.

The mind boggles.

6 comments

6 Comments so far

  1. Drake May 31st, 2009 10:19 am

    Why don’t you use generics ?

    Instead of using ArrayList use List and you won’t have any problems. Unlike java c# is much faster in usage with generics than without

  2. Joe May 31st, 2009 5:06 pm

    Yeah, I read about generics in C# a few days after this post and just never got around to making an update.

    However, I think it still stands that needing to cast an array of strings to an array of strings is fairly ludicrous. aList.ToArray(typeof(string)) *should* be sufficient, logically speaking. The fact that it’s not sufficient is problematic whether or not workarounds exist.

  3. Stephan Leclercq May 27th, 2010 10:35 am

    I don’t really understand. First, you do not have to cast anything:

    List l = new List();
    l.Add(“this”);
    l.Add(“that”);
    string[] s = l.ToArray();

    Second, why do you use an array instead of IEnumerable or IList everywhere ? Almost no part of the .NET framework explicitly requires arrays, and most components will happily gobble the IList interface, or even a less demanding one.

    C# does not suck, you simply are not fluent enough in it to appreciate it….

  4. Sanjeev Mundluru August 3rd, 2010 3:46 pm

    All arrays, both of value and reference type, derive from the abstract System.Array class. So when you declare a new string[], you are actually creating an object that derives from System.Array. This differs from C/C++ where arrays are really constructs of the language instead of objects.

    Calling ToArray(typeof(string)) creates a generic System.Array object, NOT a string[] object. The need for typeof(string) tells the compiler what type of objects are in the ArrayList so it can cast the ArrayList as a System.Array object.

    You must then cast the System.Array object to a string[] object.

    As a requirement of C# semantics, casting from an abstract class (the System.Array object) to a type that derives from that abstract class (the string[] object) must be done explicitly. Thus, the need for the additional (string[]) cast.

    So, basically, you are casting twice. Once from ArrayList to System.Array, and again from System.Array to string[].

    ArrayLists are really an antiquated way of working. Generics are meant to replace them. If you want to work with ArrayLists, you can expect a lot of casting!

  5. Sanjeev Mundluru August 3rd, 2010 4:29 pm

    By the way, if the database method you’re using returns an IEnumerable, you can cast it as a string[] in a single line of code.

    Let’s say the database method that returns the IEnumerable is Database.GetData()

    string[] mystringarray = (string[])Database.GetData();

    No need for ArrayList, ToArray(), or even List.

    Don’t complain about a language you don’t know how to use!

  6. [...] resolution ever comes of ANY flame war …despite the fact there are no end to the results that are relevant to the war at hand.  We all know flame wars are pointless, and yet we get some perverse [...]

Leave a comment