【问题标题】:Switch/case with Color带颜色的开关/外壳
【发布时间】:2013-10-28 13:31:11
【问题描述】:

快速简单的问题:

如何制作具有多种颜色的开关/外壳。

我能做的是:

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

或者我可以用旧/新颜色做一个Dictionary 来替换它们(在这个特定的例子中,除了分配新颜色之外不需要额外的工作)。

或者我可以使用 tmp 变量,所以它变成(但同样,在这种特定情况下):

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

我想要的是类似的东西

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

我发现了this 有趣的文章,我可能会决定使用它。

或者我正在考虑类似的事情

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

你们觉得哪个更好?

【问题讨论】:

  • 为什么要使用switch语句?就个人而言,我更喜欢字典方法。
  • 如果您想要执行的唯一操作是替换,那么字典似乎是最干净的选择。在 if 语句和 switch 之间,我总是更喜欢 if 语句(因为它更具适应性)。但我想这只是个人口味的方法。客观上没有比其他任何选择更好的选择。
  • @gleng,除了设置颜色之外,可能还有一些代码。它还没有,但我喜欢 clean 开关/外壳的外观,这就是原因。

标签: c# colors switch-statement case


【解决方案1】:

使用字典的代码更少,而且更灵活,因为您可以从配置文件或数据库中加载它。如果您需要更改映射,则无需重新构建代码。

【讨论】:

    【解决方案2】:

    我认为在你的情况下 KnownColor 枚举可以完成这项工作,但你在这里的颜色有限

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

    【讨论】:

    • 好吧,我有Color,最后我需要Color。找到如何将KnownColor 转换为Color。问题是如何将Color 转换为KnownColor
    • 魔鬼在细节上和往常一样……您对分析颜色的要求相当具体。所以让我们试着想象一组可以描述所有可能颜色的名称。即使有这样一组名称,每个名称都将与您的示例中的“case 129381038:”提供相同的信息。所以...如果没有办法将要求更改为 KnowColors,那么字典方法似乎是唯一可能的
    • 我实际上可以使用您的解决方案(我目前只有一种异常颜色SystemColors.ControlText,但它在KnownColors中列出),但我不知道如何用已知的Color 初始化KnownColor,我将要使用什么。有什么想法吗?
    • 老实说 - 不。我看不到将颜色转换为已知颜色的方法。甚至 Color.IKnownColor 仅在颜色是从已知颜色创建的情况下才起作用。所以我必须重复有关颜色分析的任务或对 KnownColors 或其他可能颜色集的要求限制。
    • 知道 =D 很有用
    【解决方案3】:

    我绝对认为使用字典将是最好的方法。

    但是,如果你真的喜欢 switch 语句,你可以使用 Color.Name 并打开它。 Color.Name 将返回颜色的已知名称(如果有),否则返回颜色的十六进制 argb 代码。

    这里有一些示例代码演示了这两种方法。我正在使用Lazy<> 来初始化颜色/动作映射器以避免任何潜在的线程问题:

    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();
            }
        }
    }
    

    【讨论】:

    • 当我说Dictionary 我的意思是Dictionary&lt;Color, Color&gt; 一个。但我明白Dictionary 也可能意味着Action,感谢您的解释。当我可以使用case "aarrggbb" 时,Color.Name 的想法,难道不能将其定义为 int 吗?所以我可以使用switch(color.ToArgb()) { case 0xaarrggbb: /* blablabla */ break; } 之类的东西?
    • @Sinatr 是的,您确实可以使用Color.ToArgb() 而不是Color.Name,但是在开关盒中您不会有任何颜色名称,只有数字。但如果这就是你想要的,那就去吧!
    • 唯一的问题是如何从Color 获取ARGB 号码作为constant。制作const int ColorRed = 0x00ff0000;KnownColors 的一种方式。使用color.Name 并定义const string ColorRed = "Red" 看起来比。嗯..似乎我都不喜欢得到满足,对不起=(
    • @Sinatr 是的,您无法从 Color 中获取 ARGB 数字作为常量。你必须定义你自己的。但是,您不妨改用已知颜色字符串。
    【解决方案4】:

    如果您固定使用 switch 语句,您可以执行以下操作以结合相对容易编码/人类可读性:

    switch(color.ToString())
    {
       case "Color [Red]":
          //...
          break;
       //...
    }
    

    【讨论】:

    • 很有趣,但是在没有 Intellisense 帮助的情况下输入所有颜色会有风险。以及如何处理SystemColor.ControlText
    猜你喜欢
    • 1970-01-01
    • 2015-10-20
    • 1970-01-01
    • 2010-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-26
    相关资源
    最近更新 更多