简体   繁体   English

如何使用字符串数组来处理C#中switch语句中的case?

[英]How to use an array of strings to handle the cases in a switch statement in C#?

I have an array 我有一个阵列

    public static string[] commands =
    {   
        "command1",
        "command2",
        "command3",
        "command4",
        "command5",
        "command6",
        "command7"
    };

I want to use the array in the function 我想在函数中使用数组

    public static bool startCommand (string commandName) {
        //stuff
        if (commandName == commands[0]) {
            //stuff
            return true;
        }
        else {
            //stuff
            switch (commandName) {
                case commands [1]:
                    //stuff
                    break;
                case commands [2]:
                    //stuff
                    break;
                case commands [3]:
                    //stuff
                    break;
                case commands [4]:
                    //stuff
                    break;
                case commands [5]:
                    //stuff
                    break;
                case commands [6]:
                    //stuff
                    break;
                default:
                    return false;
            }
            //do stuff
            return true;
        }
    }

The error that this is giving me is "A constant value is expected" for each of the cases. 这给我的错误是每个案例的“一个恒定值”。

I could use if and else statements, but I think the switch statement looks better for this. 我可以使用if和else语句,但我认为switch语句看起来更好。

Unless I've missed my mark, my array is of constant strings, so this should work. 除非我错过了我的标记,否则我的数组是常量字符串,所以这应该有效。 Any help would be appreciated. 任何帮助,将不胜感激。 Sorry if this is a newb question, I've been programming with C# for about four days. 很抱歉,如果这是一个新问题,我已经用C#编程了大约四天。

What you're looking for is the Dictionary<TKey, TValue> type. 您正在寻找的是Dictionary<TKey, TValue>类型。 A Dictionary is basically a collection of Key-Value pairs, something we can take advantage of for what you're attempting to achieve. Dictionary基本上是键值对的集合,我们可以利用它来实现您想要实现的目标。

Using the example you've given, the implementation would look like this: 使用您给出的示例,实现将如下所示:

Dictionary<string, Action> commandsDictionary = new Dictionary<string, Action>();
commandsDictionary.Add("Command1", () => Console.WriteLine("Command 1 invoked"));
commandsDictionary.Add("Command2", () => Console.WriteLine("Command 2 invoked"));

commandsDictionary["Command2"].Invoke();
// Command 2 invoked

As you'll have noticed, I've introduced the an Action delegate without any parameters. 正如您已经注意到的那样,我已经介绍了一个没有任何参数的Action委托。


To introduce a parameter, just specify it as a type argument, like this: Action<int> 要引入参数,只需将其指定为类型参数,如下所示: Action<int>

Dictionary<string, Action<int>> commandsDictionary = new Dictionary<string, Action<int>>();
commandsDictionary.Add("Command1", (i) => Console.WriteLine("Command {0} invoked", i));

commandsDictionary["Command1"].Invoke(1);
// Command 1 invoked

If you want to return a value from the delegate you're invoking, use the Func delegate, an easy to remember rule with Func is that the last type parameter is always the type being returned, so Func<int, string> would be equivalent to a method with the following signature public string Foo(int i) 如果要从正在调用的委托中返回一个值,请使用Func委托,一个易于记忆的Func规则是最后一个类型参数始终是返回的类型,因此Func<int, string>将是等效的到具有以下签名public string Foo(int i)

Dictionary<string, Func<int, string>> commandsDictionary = new Dictionary<string, Func<int, string>>();
commandsDictionary.Add("Command1", (i) => { return string.Format("Let's get funky {0}", i); });

string result = commandsDictionary["Command1"].Invoke(56963);
Console.WriteLine (result);
// Let's get funky 56963



Reference 参考

I've added this section to aid those who do not yet know what a delegate is... it's all actually rather simple. 我已经添加了这一部分来帮助那些还不知道代表是什么的人...这一切都非常简单。


Delegates 代表

A Delegate is a Type that represents references to methods . Delegate是一个表示方法 引用Type They're just like variables that you declare to reference objects, except instead of objects, they reference methods. 它们就像你声明引用对象的变量一样,除了代替对象,它们引用方法。

A delegate can be instantiated with a named method or an anonymous function such as a lambda expression (which is the type I've demonstrated above). 委托可以使用命名方法匿名函数(例如lambda表达式(我在上面演示的类型))进行实例化。


The Action Delegate 行动代表

The Action Delegate has a return type of void and defines its signature with type parameters. Action Delegate的返回类型为void,并使用类型参数定义其签名。

void Example()
{
    // Named method
    this.NamedActionDelegate = NamedMethod;
    this.NamedActionDelegate.Invoke("Hi", 5);
    // Output > Named said: Hi 5

    // Anonymous Function > Lambda
    this.AnonymousActionDelegate.Invoke("Foooo", 106);
    // Output > Anonymous said: Foooo 106
}

public Action<string, int> NamedActionDelegate { get; set; }
public Action<string, int> AnonymousActionDelegate = (text, digit) => Console.WriteLine ("Anonymous said: {0} {1}", text, digit);

public void NamedMethod(string text, int digit)
{
    Console.WriteLine ("Named said: {0} {1}", text, digit);
}

The Func Delegate Func代表

The Func Delegate is similar to the Action Delegate the difference being that Func never returns void and thus will always require at least 1 type argument and as mentioned earlier, the type argument specified last dictates the return type of the delegate. Func Delegate类似于Action Delegate,区别在于Func从不返回void ,因此总是需要至少1个类型参数 ,如前所述,最后指定的type参数指示委托的返回类型。

void Example()
{
    // Named method
    this.NamedFuncDelegate = NamedMethod;
    string namedResult = this.NamedFuncDelegate.Invoke(5);
    Console.WriteLine (namedResult);
    // Output > Named said: 5

    // Anonymous Function > Lambda
    string anonyResult = this.AnonymousFuncDelegate.Invoke(106);
    Console.WriteLine (anonyResult);
    // Output > Anonymous said: 106
}

public Func<int, string> NamedFuncDelegate { get; set; }
public Func<int, string> AnonymousFuncDelegate = (digit) => { return string.Format("Anonymous said: {0}", digit); };

public string NamedMethod(int digit)
{
    return string.Format ("Named said: {0}", digit);
}

If you want to use the switch with the array commands, instead use of compare with the items of commands use the index statement like this: 如果要将开关与数组命令一起使用,而是使用与命令项比较,请使用索引语句,如下所示:

public static string[] commands =
{   
    "command1",
    "command2",
    "command3",
    "command4",
    "command5",
    "command6",
    "command7"
};

public static bool startCommand(string commandName)
{
    var index = Array.IndexOf(commands, commandName);

    //stuff
    if (index == 0)  // commands[0]
    {
        //stuff
        return true;
    }
    else
    {
        //stuff
        switch (index)
        {
            case 1:  // commands[0]
                //stuff
                break;
            case 2:  // commands[2]
                //stuff
                break;
            case 3:  // commands[3]
                //stuff
                break;
            case 4:  // commands[4]
                //stuff
                break;
            case 5:  // commands[5]
                //stuff
                break;
            case 6:  // commands[6]
                //stuff
                break;
            default:
                return false;
        }
        //do stuff
        return true;
    }
}

To summarize as an answer, change it to something like this: 要总结为答案,请将其更改为以下内容:

        Dictionary<string, Action> commands = new Dictionary<string,Action>();
        commands.Add("command1", () => {});
        commands.Add("command2", () => { });
        commands.Add("command3", () => { });

        Action action = null;
        commands.TryGetValue(commandName, out action);
        if (action != null) 
            action();

You can make your dictionary static, or possibly readonly if you want: 如果需要,您可以使字典静态,或者可能只读:

    static void Command1() { }
    static void Command2() { }

    static readonly Dictionary<string, Action> commands = new Dictionary<string, Action>(){
        { "command1", Command1 },
        { "command2", Command2 }
    };

Assuming you are ok with constant strings, what about defining a static class: 假设你对常量字符串没问题,那么定义静态类怎么样:

public static class COMMANDS 
{
    public const string COMMAND1 = "command1";
    public const string COMMAND2 = "command2";
    public const string COMMAND3 = "command3";
    public const string COMMAND4 = "command4";
    public const string COMMAND5 = "command5";
    public const string COMMAND6 = "command6";
    public const string COMMAND7 = "command7";
}

and then use it with the switch statement: 然后将它与switch语句一起使用:

//stuff
if (commandName == COMMANDS.COMMAND1)
{
    //stuff
    return true;
}
else
{
    //stuff
    switch (commandName)
    {
        case COMMANDS.COMMAND2:
            //stuff
            break;
        case COMMANDS.COMMAND3:
            //stuff
            break;
        case COMMANDS.COMMAND4:
            //stuff
            break;
        case COMMANDS.COMMAND5:
            //stuff
            break;
        case COMMANDS.COMMAND6:
            //stuff
            break;
        case COMMANDS.COMMAND7:
            //stuff
            break;
        default:
            return false;
    }
    //do stuff
    return true;
}
using System;
using System.Reflection;

namespace CommandExample
{
    class Program
    {
        static void Main()
        {
            var cmdName = "Command1";

            // Create an instance of the command class using reflection
            Type type = Assembly.GetExecutingAssembly().GetType("CommandExample." + cmdName);
            if (type == null) { /* Cannot find command. Handle error */ }
            var cmd = Activator.CreateInstance(type) as ICommand;

            cmd.Exec();
        }
    }

    interface ICommand
    {
        void Exec();
    }

    class Command1 : ICommand
    {
        public void Exec()
        {
            Console.WriteLine("Executing Command1");
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM