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.
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.
What you're looking for is the Dictionary<TKey, TValue>
type. A Dictionary
is basically a collection of Key-Value pairs, something we can take advantage of for what you're attempting to achieve.
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.
To introduce a parameter, just specify it as a type argument, like this: 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)
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
I've added this section to aid those who do not yet know what a delegate is... it's all actually rather simple.
A Delegate
is a Type
that represents references to methods . 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).
The Action
Delegate
has a return type of void and defines its signature with type parameters.
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
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.
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:
//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");
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.