LA.NET [EN]

Apr 16

[Update: Thanks to Mike for uncovering a bug on the sample. It should be IDummy.Increment and not Dumy.Increment. Thanks Mike and now I think it should compile without any problems.]

In these last days I”ve been reading the C# spec and you can say that I”ve been re-discovering it :,,) If you really think about it, I think that it”s fair to say that most people will only use the basic features of the language. And since many things work as they should (ie, they work in a logical manner), most of us don”t take the necessary time to study the spec.

Let me show you a little example that will help me make a point about this:) Look at the following example and tell me what happens (this example is based on an existing example that is shown on the C# spec):

using System;

namespace CSharpGotchas
{
    public interface IDummy
    {
        void Increment();
    }

    public struct IDummy : IDummy
    {
        public Int32 Counter; 
        void IDummy.Increment()
        {
            Counter++;
            Console.WriteLine(Counter);
        } 
    }

    public class GenericDummy<T> where T : IDummy, new()
    {
        public void Increment()
        {
            var aux = new T();
            aux.Increment();
            aux.Increment();
            aux.Increment();
        }
    }

    internal class Program
    {
        private static void Main(string[] args)
        {
            var aux = new GenericDummy<Dummy>();
            aux.Increment();
        }
    }
}

I”ve showed this example to several guys I know (I think that most of them had at least 1 year experience in C# programming) and only I knew the correct answer.

btw, if you”ve been using C# and .NET for some time, haven”t read the spec and don”t see anything that might make you think twice before answering, then you should be worried :)

Ok, the problem here is what should be printed on the console. Should we get 1, 1, 1 or should we get 1, 2, 3? if Dummy was a class, there really wouldn”t be any problems with the code since you would always be working with a reference element. But since Dummy is a struct, will we have boxing when calling Increment? (Do notice that I”ve implemented the IDummy interface explicitly, making it accessible only through an interface reference).

If you”re thinking that the previous code will print 1, 2, 3, you”re right! Why? well, because the spec explictly says that there are certain cases where it won”t box a struct. One of those cases happens when a struct overrides a method inherited from the System.Object class. Invocation of that method will be made directly over that instance of the struct (ie, you won”t be getting a boxed instance over which the method call is made).

Another place where you don”t get implicit boxing is when you acess a member or variable of a constrained type parameter (that is the case shown on the previous example). On the other hand, if you box the element by casting it to the interface, you”ll always get 1. Here”s an example that shows this:

public class GenericDummy<T> where T : IDummy, new()
{
        public void Increment()
        {
            var aux = new T();
            ((IDummy)aux).Increment();
            ((IDummy)aux).Increment();
            ((IDummy)aux).Increment();
        }
}

btw, I”m curious: did you know this?

2 comments so far

  1. Mike
    8:13 am - 4-17-2008

    But did you actually get this code to build ?

    In VS2008, I get two errors :

    1. ”Dummy” in explicit interface declaration is not an interface
    2. ”CSharpGotchas.Dummy” does not implement interface member ”CSharpGotchas.IDummy.Increment()”

    So I guess the correct answer should be that it won”t compile !

  2. Mike
    11:27 am - 4-17-2008

    But if you replace :

    void Dummy.Increment()

    with

    void IDummy.Increment()

    then it does compile

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>