C# – Be careful when using struct to implement interface

All .net programmers know class can implement interface but I think that not all of them know a struct can implement an interface too. But there are a problem that we should take care when we use struct to implement interface. In this example below I would like to make a small example to demonstrate the problem. The complete source code is below. We just modify some words to cause problem.

interface IAccount
{
	void UpLevel();
}

class GameAccount : IAccount
{
	public string Name;
	public int Level;

	public GameAccount(string strName, int nLevel)
	{
		Name = strName;
		Level = nLevel;
	}

	public override string ToString()
	{
		return String.Format("{0} {1}", Name, Level);
	}

	#region IAccount Members

	public void UpLevel()
	{
		Level++;
	}

	#endregion
}

class Program
{
	static void Main(string[] args)
	{
		GameAccount gaAcc = new GameAccount("rongchaua", 95);
		IAccount iaAcc = gaAcc;
		Console.WriteLine(gaAcc);
		iaAcc.UpLevel();
		Console.WriteLine(gaAcc);
		Console.ReadLine();
	}
}

In the code snippet above I show a completely normal code in which I define an interface and a class to implement it. Run the program, you can see on the console screen.

It’s ok. The code does as we want. Variable of type IAccount iaAcc points exactly to memory space of gaAcc and when we increase level, the level of gaAcc object will increase too. Perfect. Now change class GameAccount to a struct.

struct GameAccount : IAccount
{
	 ...
}

What happens here now? Why do we have a false result? Obviously a boxing occurs here. When we casting a struct to interface, the compiler will automatically “box” it to a temporary class object and then the interface variable will point to this temporary class object, not the original struct any more. Therefore when we increase level, we are increasing the level of the temporary object, not the level of struct gaAcc.
So maybe you have another question. Ok, an automatic boxing took place. Why don’t we try to out boxing and test if the reference still works?

static void Main(string[] args)
{
	GameAccount gaAcc01 = new GameAccount("rongchaua", 95);
	GameAccount gaAcc02 = gaAcc01;
	Console.WriteLine(gaAcc01);
	gaAcc02.UpLevel();
	Console.WriteLine(gaAcc01);
	Console.ReadLine();
}

And the result is

Conclusion: Struct is a value-type. Be careful when using struct to implement your interface.