I think enum values are treated like boxed ints by default, although IIRC it's possible to use other types for the values. Whatever it is there's runtime type information available to know what enum type the value belongs to. And we're allowed to cast between enums in the somewhat optimistic hope that their underlying values correspond. This much can be shown by running the following simple application (requires you to create a new windows forms app and drop a button on the form and wire up the click event, as I don't include the designer.cs file here).
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
enum en { Zero, One, Two, Three };
enum fr { Nul, Un, Deux, Trois };
void foo(object obj)
{
if (obj is en) dbug("en:{0} => fr:{1}", obj, (fr)obj);
else if (obj is fr) dbug("fr:{0} => en:{1}", obj, (en)obj);
else dbug("?:{0} => en:{1}, fr:{2}", obj, (en)obj, (fr)obj);
}
void dbug(string s, params object\[\] args)
{
if (args.Length > 0) s = string.Format(s, args);
Debug.WriteLine(s);
}
void button1\_Click(object sender, EventArgs e)
{
Random r = new Random();
for (int i = 0; i < 20; i++)
{
object v = r.Next(4);
if (r.Next(100) < 33)
foo((en)v);
else if (r.Next(100) < 50)
foo((fr)v);
else foo(v);
Thread.Sleep(500);
}
}
}