Structs and interfaces

I ran into an interesting tidbit the other day: a couple of structs implementing and interface. That just seems like asking for trouble to me, structs are value types and interfaces are reference types. Something tells me there could be some subtle issues associated with this. It’s pretty clear that boxing will occur when you pass a value type as a reference type, but I’m sure that’s not the only issue we’ll see here. Time for a quick study.

Here’s the interface we’ll be implementing:

   1: public interface IPlayer
   2: {
   3:     string Name { get; set; }
   4:     string Club { get; set; }
   5:     int Age { get; set; }
   6:  
   7:     void Transfer(string newClub);
   8: }

And here’s a real simple implementation for it:

   1: public struct Player : IPlayer
   2: {
   3:     public string Name { get; set; }
   4:     
   5:     private string club;
   6:     public string Club
   7:     {
   8:         get { return club; }
   9:         set { club = value; }
  10:     }
  11:  
  12:     public int Age { get; set; }
  13:  
  14:     public void Transfer(string newClub)
  15:     {
  16:         club = newClub;
  17:     }
  18: }

So we’re just going to go ahead and create an instance of a player. Once we have that we’ll print the club he’s currently playing for and we’ll transfer him to a different club (and make a lot of money in the process).

   1: Player player = new Player {Age = 20, Club = "AC Milan", Name = "Marco van Basten"};
   2: player.Transfer("Ajax Amsterdam");
   3:  
   4: Console.WriteLine(player.Club);

It’s not too hard to guess this will output “Ajax Amsterdam”. Now what happens if we transfer Marco back to AC Milan, but using the IPlayer interface now? Let’s see.

   1: IPlayer copy = player;
   2: copy.Transfer("AC Milan");
   3:  
   4: Console.WriteLine(player.Club);

Looks like Marco still plays for Amsterdam even though we  just transferred him to Milan. Tough! Well, what happened? The implicit cast created a temporary object we updated and threw away. Not good. Now if we changed the Player struct to a class it would all work as expected.

I would stay away from structs implementing interfaces, just make it a class instead.


Back to basics - Intro

After some though I came up with an idea on a multi-part article that I think will be useful. It will cover one aspect of programming I am currently struggling with at work - namely persistence.

I believe, as Ayende puts it, that the persistence problem has been solved. On my personal projects I use NHibernate with some very good success. It's been hard-fought and I'm the first to admit there is quite the learning curve to it. But in the long run it's worth it.

At work, on the other hand, we use table gateways and we end up with reams of transaction scripts spread throughout the application. It is procedural programming disguised as objects, and the issues associated with it are numerous and a constant source of pain and suffering - at least for me. Code duplication is rampant, business logic is frequently implemented in stored procedures - which subsequently become un-usable in other areas of the application. A fair amount of logic is spread trough the code behind of pages and sometimes as orphan classes in the App_data folder of all places.

I've spoken to a couple of colleagues about NHibernate and OR\M in general but there seems to be a disconnect somewhere. I suspect the issue is with a lack of understanding of the basic OR\M patterns that enable a rich domain model and encapsulate the complexities of persistence.

This mini-series will be about basic OR\M patterns, and it's intended to provide a side by side comparison of the options available to us - from hand rolled to meta data driven. I will try to demonstrate - with code, not just talk - the advantages and disadvantages of different patterns, hopefully evolving from one to the next organically, as the requirements become more complex. I have a feeling I'm under estimating this in more ways than one, but we'll see where it goes.

As always feedback is always welcome.


Search

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2010