C# Puzzles – Puzzle #2: Static Generics

Photo by Sid Balachandran

For this puzzle, there is a little code snippet at the end that may help you in the future. The puzzle really isn’t super hard to figure out. Unfortunately, it is a either you know it or you don’t.

Note: Scroll selectively to not spoil the results.

Lets jump into it.

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(MyClass<string>.Method("Hello"));
            Console.WriteLine(MyClass<string>.Method("World"));
            Console.WriteLine(MyClass<char>.Method('!'));


            Console.ReadLine();
        }
    }

    public static class MyClass<T>
    {
        public static Guid Guid => Guid.NewGuid();

        public static string Method(T item)
        {
            return $"{typeof(T).Name} {Guid} {item}";
        }
    }

What do you expect the output to be?






Space to avoid spoilers.




Nothing super surprising. Three different Guids are created, because the property is returning a new value every time. Let’s change the code so it doesn’t now.

Interesting Tidbit: Microsoft recommends properties to not be self changing. It recommends methods to be used instead of properties for values that can change without class manipulation. This is why Guid.NewGuid() is a method. Notably, DateTime.Now is a property but it is considered a design mistake.

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(MyClass<string>.Method("Hello"));
            Console.WriteLine(MyClass<string>.Method("World"));
            Console.WriteLine(MyClass<char>.Method('!'));


            Console.ReadLine();
        }
    }

    public static class MyClass<T>
    {
        public static Guid Guid { get; } = Guid.NewGuid();

        public static string Method(T item)
        {
            return $"{typeof(T).Name} {Guid} {item}";
        }
    }

What do you expect the output to be now?






Space to avoid spoilers.




Now we get 2 different Guids. One for string and one for the char. Do you know why? Well most are not surprised by this behavior, but it is a different behavior that Java would produce. Java, or at least older versions of Java (I’m not 100% sure on current), would create a Type MyClass<T> then they cast the variable coming in and out as the Type when used. So there is only one definition of MyClass.

.NET though creates a Type specific for every generic used. This means there is a Type created at run-time for both string and char. .NET will create each method as they are used for the generic, specific for that generic. This means we actually end up with two static classes create. MyClass<string> and MyClass<char>.

Let’s build on top of this for a minute though.

class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(MyClass.Method("Hello"));
            Console.WriteLine(MyClass.Method("World"));
            Console.WriteLine(MyClass.Method('!'));


            Console.ReadLine();
        }
    }

    public static class MyClass
    {
        private static Guid Guid { get; } = Guid.NewGuid();

        public static string Method<T>(T item)
        {
            return MyGeneric<T>.Method(item);
        }


        private static class MyGeneric<T>
        {
            private static Guid GenericGuid { get; } = Guid.NewGuid();

            public static string Method(T item)
            {
                return $"{typeof(T).Name} {Guid} {GenericGuid} {item}";
            }
        }
    }

If we remove the generic from MyClass, keep the generic on the method, and create a sub class with a generic we can have both behaviors. Additionally, when calling the generic method we no longer need to specific the generic. Where before we had to on the class.

Personally, I will follow this paradigm when dealing with static generic members. It keeps the external usage simple. The output is as expected. Guid is defined once, GenericGuid is defined per type.

Although this is great at keeping your API clean it does have an additional side effect. It is faster than a dictionary where the key is Type.

As far as a simple test goes, this is just comparing the reading between a dictionary and a generic static variable.

   class Program
    {
        static void Main(string[] args)
        {

            var watch = Stopwatch.StartNew();
            for (var i = 0; i < 10000; i++)
            {
                GenericSubclass.Method<string>();
                GenericSubclass.Method<object>();
                GenericSubclass.Method<int>();
                GenericSubclass.Method<DateTime>();
            }
            watch.Stop();

            Console.WriteLine(watch.Elapsed.Ticks);

            watch.Restart();
            for (var i = 0; i < 10000; i++)
            {
                TypeDictionary.Method<string>();
                TypeDictionary.Method<object>();
                TypeDictionary.Method<int>();
                TypeDictionary.Method<DateTime>();
            }
            watch.Stop();

            Console.WriteLine(watch.Elapsed.Ticks);

            Console.ReadLine();
        }
    }

    public static class GenericSubclass
    {

        public static Guid Method<T>()
        {
            return SubClass1<T>.Guid;
        }

        public static class SubClass1<T>
        {
            public static Guid Guid = Guid.NewGuid();
        }
    }

    public static class TypeDictionary
    {
        public static Dictionary<Type, Guid> lookup = new Dictionary<Type, Guid>
        {
            {typeof(int),  Guid.NewGuid() },
            {typeof(string), Guid.NewGuid() },
            {typeof(object), Guid.NewGuid() },
            {typeof(DateTime), Guid.NewGuid() }
        };


        public static Guid Method<T>()
        {
            return lookup[typeof(T)];
        }
    }

In my testing the Generic Subclass performs 10 times faster than the dictionary. This although is really negligible because the dictionary is still really fast. Both need to be measured in Ticks to even compare the two.

Personally I like the Static Generic Subclass, as Dictionary<Type, object> and lookup[typeof(T)] always felt strange to me.

There is something that actually makes a lot of sense with this pattern though. When using expressions, funcs, or actions, you can keep the generics for those while not complicating your API. Just a thought.

So instead of having a Dictionary<Type, object> and having to cast to let’s say Action<T> for a cache, having a Static Generic Subclass could keep your generic defined properly and you wouldn’t have to cast or do typeof.

Hope you enjoyed and learned something.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: