Quantcast
Viewing all articles
Browse latest Browse all 10

C# Enum Quirks

I’ve been slashing out C# code since 2000. Just today I discovered something totally new to me.

Would you reckon that this test is valid?

public enum Direction
{
	Left,
	Right 
}

[TestClass]
public class EnumQuirks
{
	[TestMethod]
	public void Cast_any_number_to_enum()
	{
		Direction direction = (Direction)5;
		Assert.AreEqual(5, (int)direction);
	}
}

In fact, it is. An enumeration can be casted to its underlying data type, of course; by default, this is an Int32. What I hadn’t realized is that the conversion works the other way too. Any integer value can be assigned to an enum, whether the values are defined or not. In order to safely assign a numeric value, the result of Enum.IsDefined can be evaluated.

But it gets weirder. In order to convert a string value into an enum, there’s the TryParse method. But when it tries parsing really hard, look what it can do:

[TestMethod]
public void TryParse_accepts_any_number_in_string()
{
	string value = "5";
	Direction direction;
	bool canParse = Enum.TryParse(value, out direction);
	Assert.AreEqual(5, (int)direction);
	Assert.IsTrue(canParse);
}

This is even documented:

Enum.TryParse: Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object.

It converts the numeric value too. And since there is no check if there is a constant defined for any numeric value, any string that can be parsed to a number is valid.

Lesson learned: you can’t trust assignments to enumerations without checking Enum.IsDefined. And if there’s code out there that parses string coming from an insecure source (like an web request), you can’t rely on Enum.TryParse.


Image may be NSFW.
Clik here to view.
Image may be NSFW.
Clik here to view.

Viewing all articles
Browse latest Browse all 10

Trending Articles