Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Singletons using structs in C#

This isn't really an optimization question or anything. It's essentially a what-the-heck-is-going-on-here kind of question. The singleton pattern is used to have a single instance of an object used multiple times. That's all well and good, but if I try to do a similar pattern with a struct, it don't get a single instance.

I came about this trying to do something with the Color struct in System.Drawing. Here is some example code:

    class Colors
    {
        private static Color _red;
        public static Color Red
        {
            get
            {
                if (_red.IsEmpty)
                    _red = Color.FromArgb(0xFF, 0xFF, 0x42, 0x39);

                return _red;
            }
        }
    }

    static void Main(string[] args)
    {
        var redOne = Colors.Red;
        var redTwo = Colors.Red;

        Console.WriteLine("redOne.Equals(redTwo) : {0}", redOne.Equals(redTwo));
        Console.WriteLine("redOne == redTwo : {0}", redOne == redTwo);
        Console.WriteLine("Object.Equals(redOne, redTwo) : {0}", Object.Equals(redOne, redTwo));
        Console.WriteLine("Object.ReferenceEquals(redOne, redTwo) : {0}", Object.ReferenceEquals(redOne, redTwo));
        Console.ReadLine();
    }

The output for this is:

redOne.Equals(redTwo) : True
redone == redTwo : True
Object.Equals(redOne, redTwo) : True
Object.ReferenceEquals(redOne, redTwo) : False

The first three results are to be expected, but the last is what surprised me. Now, my best guess is that when _red is returned from Colors.Red it's returning a copy, as normal value types do. So, while there is only a single instance of _red, Colors.Red returns a brand new instance, and that is what gets stored into redOne and redTwo. Is my thinking correct?

Also, if that is correct, is there any point in using the static keyword on structs?

Thanks

like image 447
yellow_nimbus Avatar asked Sep 15 '25 07:09

yellow_nimbus


1 Answers

ReferenceEquals will not work with a struct/value type, only a class.

Calling ReferenceEquals on two structs will 'box' each struct into it's own memory location and then compare the two (obviously) different addresses.

Since a class is already a reference type, the call to ReferenceEquals compares the actual address of the instance.

Essentially you do not need to store a static copy of 'Red'. Change the code to the following:

class Colors
{
    public static Color Red
    {
        get
        {
            return Color.FromArgb(0xFF, 0xFF, 0x42, 0x39);
        }
    }
}

Additional reading: MSDN - Structs (C# Programming Guide)

like image 154
csharptest.net Avatar answered Sep 17 '25 21:09

csharptest.net