Switch/case with Color

10,795

Solution 1

Using a Dictionary is less code and more flexible as you can load it from a configuration file or the database. If you need to change the mapping, you won't have to rebuild your code.

Solution 2

I think in your case KnownColor enum will do the job, but you are limitted with the colors here

    var c = KnownColor.Red;

    switch (c)
    {
        case KnownColor.Red:
            Console.WriteLine("true");
            break;
        default:
            Console.WriteLine("False");
            break;
    }

Solution 3

I definitely think that using a dictionary is going to be the best approach.

However, if you really like switch statements, you could use Color.Name and switch on that. Color.Name will return the known name of the colour, if any, or the hexadecimal argb code for the colour if not.

Here's some sample code that demonstrates both approaches. I'm using a Lazy<> to initialise the colour/action mapper to avoid any potental thread issues:

using System;
using System.Collections.Generic;
using System.Drawing;

namespace Demo
{
    class Program
    {
        private void run()
        {
            test1(Color.Red);
            test1(Color.Green);
            test1(Color.FromArgb(0xea, 0x36, 0xbe));
            test1(Color.FromArgb(0x24, 0x67, 0xc0));

            test2(Color.Red);
            test2(Color.Green);
            test2(Color.FromArgb(0xea, 0x36, 0xbe));
            test2(Color.FromArgb(0x24, 0x67, 0xc0));
        }

        private void test1(Color colour)
        {
            switch (colour.Name)
            {
                case "Red":
                {
                    Console.WriteLine("Red");
                    break;
                }

                case "Green":
                {
                    Console.WriteLine("Green");
                    break;
                }

                case "ffea36be":
                {
                    Console.WriteLine("My custom colour");
                    break;
                }

                default:
                {
                    Console.WriteLine("Unknown colour: " + colour.Name);
                    break;
                }
            }
        }

        private void test2(Color colour)
        {
            Action action;

            if (_colourMapper.Value.TryGetValue(colour, out action))
                action();
            else
                Console.WriteLine("Unknown colour: " + colour.Name);
        }

        private static Dictionary<Color, Action> createColourMapper()
        {
            var result = new Dictionary<Color, Action>();

            result[Color.Red] =                        () => Console.WriteLine("Red");
            result[Color.Green] =                      () => Console.WriteLine("Green");
            result[Color.FromArgb(0xea, 0x36, 0xbe)] = () => Console.WriteLine("My custom colour");

            return result;
        }

        private readonly Lazy<Dictionary<Color, Action>> _colourMapper = new Lazy<Dictionary<Color, Action>>(createColourMapper);

        static void Main(string[] args)
        {
            new Program().run();
        }
    }
}
Share:
10,795
Sinatr
Author by

Sinatr

c#, winforms, wpf

Updated on June 04, 2022

Comments

  • Sinatr
    Sinatr almost 2 years

    Quick and easy question:

    How to make switch/case with lots of Colors.

    What I can do is:

    if(color == Color.Red)
        color = Color.Green;
    else
    {
        if(color == Color.Green)
            color = Color.Blue;
        else
        {
            // ...
        }
    }
    

    or I can do a Dictionary with old/new color to replace them (in this specific example, there is no additional work needed apart from assigning a new color).

    or I can use tmp variable, so it become (but again, in this specific case):

    Color tmp = Color.Transparent; // or whatever
    if(color == Color.Red)
        tmp = Color.Green;
    if(color == Color.Green)
        tmp = Color.Blue;
    //...
    color = tmp;
    

    What I want is something like

    switch(color)
    {
        case Color.Red:
            // ...
            break;
        case Color.Green:
            // ...
            break;
        case Color.Blue:
            // ...
            break;
    }
    

    I found this interesting article, which I may decide to use.

    Or I was thinking about something like

    switch(color.ToArgb())
    {
        case 129381038: // Color.Red?? how to put it here nicely?
            // ...
    }
    

    What you guys think is better?

  • Sinatr
    Sinatr over 10 years
    Well, I have Color and I need Color at the end. Found how to convert KnownColor to Color. The question is how to convert Color to KnownColor ?
  • Sinatr
    Sinatr over 10 years
    Is interesting, but typing all the colors without Intellisense help would be risky. And what to do with SystemColor.ControlText ?
  • Sinatr
    Sinatr over 10 years
    When I say Dictionary I mean Dictionary<Color, Color> one. But I see what Dictionary could also mean Action, thanks for explaining that. And idea with Color.Name when I can use case "aarrggbb", wouldn't it be possible to define that as int? So I can use something like switch(color.ToArgb()) { case 0xaarrggbb: /* blablabla */ break; } ?
  • Yaugen Vlasau
    Yaugen Vlasau over 10 years
    the devil is as usual in details... your requirement to analyse the color is rather specific. so let try to imaging a set of names that could describe all possible colors. even if there is such a set of names each name will be the same informative as "case 129381038:" from your example. so... if there is no way to change requiremts to KnowColors, than the Dictionary approach seems to be the only possible
  • Sinatr
    Sinatr over 10 years
    I could actually use your solution (I have so far only one abnormal color SystemColors.ControlText, but it is listed in KnownColors), but I don't know how to initialize KnownColor with known Color, what I am about to work with. Any ideas?
  • Yaugen Vlasau
    Yaugen Vlasau over 10 years
    honestly - no. I cannt see a way convert color to known color. even Color.IKnownColor work only in case the color was created from a known color. so I have to reapeat it either task about color analisys or reqirements restriction to KnownColors or other set possible of colors.
  • Matthew Watson
    Matthew Watson over 10 years
    @Sinatr Yes you could indeed use Color.ToArgb() instead of Color.Name, but then you wouldn't have any colour names in the switch cases, just numbers. But if that's what you want, then it's good to go!
  • Sinatr
    Sinatr over 10 years
    It was useful to know =D
  • Sinatr
    Sinatr over 10 years
    The only questions is how to get ARGB numbers from Color as a constant. Making const int ColorRed = 0x00ff0000; is a way to KnownColors. Using color.Name and defining const string ColorRed = "Red" looks better than. Hmm.. seems I don't like either enough to get satisfied, sorry =(
  • Matthew Watson
    Matthew Watson over 10 years
    @Sinatr Aye, you can't get ARGB numbers from Color as constants. You'd have to define your own. But then you might as well use know colour strings instead.