Thursday, February 18, 2010

Should ArrayList Be Deprecated?

I came across a poster on the Microsoft Forums the other day, who was asking a question about the .NET ArrayList. Whenever I hear the word, I cringe. Since the advent of generics, I've never once used ArrayList.

That being said, some of you may have, so I'd like to hear what you think.

Should ArrayList be deprecated, perhaps with a deprecation message that points the user to List?

Feel free to vote in the poll on the right, or leave your comments below.

Tuesday, February 16, 2010

What's wrong with this picture?


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication95
{
class Program
{
private List<string> _items = new List<string>();

public List<string> Items
{
get { return _items.ToList(); }
set { _items = value; }
}
static void Main(string[] args)
{
Program program = new Program();
program.Items = new List<string> { "One", "Two", "Three" };
program.Items.Add("Four");
foreach (var item in program.Items)
Console.WriteLine(item);
Console.ReadLine();
}
}
}


What do you think this code will do?

It may not be what you think.

Thursday, October 29, 2009

Scary Halloween-Style C# 4.0 Code

Check out the following code:

using System;
using System.Dynamic;

namespace ConsoleApplication9
{
class Program
{
static void Main(string[] args)
{
dynamic d = new ExpandoObject();
d.Hola = "Howdy";
SaySomething(d);
}

void SaySomething(dynamic d)
{
Console.WriteLine(d.Hola);
}
}
}

What do you think this code should do? There's no static method to accept the incoming parameter, so compile error, right?

Wrong.

This compiles, but blows up at runtime with a RuntimeBinderException, not finding the instance method SaySomething.



While the above compiles just fine, the following does not:

using System;
using System.Dynamic;

namespace ConsoleApplication9
{
class Program
{
static void Main(string[] args)
{
dynamic d = new ExpandoObject();
d.Hola = "Howdy";
SaySomething(d);
}
}
}

Rightly recognizing that SaySomething doesn't exist in the current context.

This is the scariest thing I've seen all week. And I was in Austin last weekend.

So why does it do this? This goes back to the way that overload resolution is achieved during compilation. Eric Lippert wrote about this problem in C# 3.0 earlier this year. Overload resolution steps (for C# 3.0) are as follows, in this order:

1. First, each overload is examined according to it's arguments.
2. Next the determination of whether or not the overload is accessible from the current static or instance context is made.
3. If the overload selected from step 1 is inaccessible, then a compile-time error is thrown.

Now, let's look at the situation I posed above. The major difference here is when this resolution occurs. The first example actually compiles, because the overload resolution is delayed until runtime. The order of operations, however, stays the same.

At runtime, these steps are performed in the following order:

1. First, each overload is examined according to it's arguments.
2. Next the determination of whether or not the overload is accessible from the current static or instance context is made.
3. If the overload selected from step 1 is inaccessible, then a run-time error is thrown.

In other words, the rules are exactly the same as they were in C# 3.0, but the consequences of this mistake while using dynamic are much more severe than they are when not using the dynamic type.

All this to say, the dynamic type is a nice addition to the C# toolbox, but it needs to be used with extreme care.

With great power comes great responsibility.