1

好吧,我不知道如何解释好.. 但我有一个 switch 语句,

string mystring = "hello";
switch(mystring)
{
case "hello":
break;
case "goodbye":
break;
case "example":
break;
}

当然这是一个例子,在实际情况下,每种情况都会发生不同的事情。好的,希望您明白这一点,现在,手动执行此操作是不可能的,因为不同案例的数量众多。我需要分别创建一个所有情况的列表,例如..对于上面的 switch 语句,我需要

string[] list = { "hello", "goodbye", "example" };

也许可以用 foreach 完成一些我不知道的事情,任何帮助将不胜感激。

此外,提供的任何工作代码都会很棒!

编辑:人们要求更多细节,所以这是它的工作原理。程序的用户输入一系列字符串。根据他们输入的字符串,它会做一些 if 和 else if 并基本上扔回新的字符串。我需要能够通过程序创建所有可用选项的列表。而且我不能只列出一个列表并将其硬编码,因为我总是在语句中添加更多案例,而且我不能返回并保持列表是最新的。

4

9 回答 9

4

对于视觉工作室:

如果 mystring 是枚举而不是字符串,则在 Visual Studio 中,如果您键入“switch”[TAB]“mystring”[ENTER],它将在所有情况下为您构建长开关。

于 2009-10-30T00:21:52.837 回答
2

这取决于您想变得多么聪明...您可以创建一个自定义属性,该属性附加到方法应处理的字符串。switch然后,您只需找到具有所需值的属性并执行它,而不是语句。

using System;
using System.Reflection;

namespace ConsoleApplication1 {
    [AttributeUsage(AttributeTargets.Method)]
    internal class ProvidesAttribute : Attribute {
        private String[] _strings;
        public ProvidesAttribute(params String[] strings) {
            _strings = strings;
        }
        public bool Contains(String str) {
            foreach (String test in _strings) {
                if (test.Equals(str)) {
                    return true;
                }
            }
            return false;
        }
    }

    internal class Program {
        [Provides("hello", "goodbye")]
        public void HandleSomeStuff(String str) {
            Console.WriteLine("some stuff: {0}", str);
        }

        [Provides("this")]
        public void HandleMoreStuff(String str) {
            Console.WriteLine("more stuff: {0}", str);
        }

        public void HandleString(String str) {
            // we could loop through each Type in the assembly here instead of just looking at the
            // methods of Program; this would allow us to push our "providers" out to other classes
            MethodInfo[] methods = typeof(Program).GetMethods();
            foreach (MethodInfo method in methods) {
                Attribute attr = Attribute.GetCustomAttribute(method, typeof(ProvidesAttribute));
                ProvidesAttribute prov = attr as ProvidesAttribute;
                if ((prov != null) && (prov.Contains(str))) {
                    method.Invoke(this, new Object[] { str } );
                    break;  // removing this enables multiple "providers"
                }
            }
        }

        internal static void Main(String[] args) {
            Program prog = new Program();
            foreach (String str in args) {
                prog.HandleString(str);
            }
        }
    }
}

一旦你有了框架,你就不需要改变HandleString()代码,只需添加你想要处理的方法并设置Provides它们的属性。如果你想进一步扩展这个想法,你可以创建多个类来处理各种各样的字符串,然后循环遍历程序集中的每个类型以查找Provides属性。

编辑这有一个额外的好处,您可以定义作用于同一字符串的多个方法(通过删除break循环逻辑)。

于 2009-10-30T00:11:11.110 回答
2

我注意到你正在尝试做什么,但你也许可以使用字典。

    Dictionary<string, int> lookupTable = new Dictionary<string, int>();

    lookupTable.Add("hello", 1);
    lookupTable.Add("goodbye", 2);
    lookupTable.Add("example", 3);


    int output = lookupTable["hello"];

您不需要有代码来添加每个单独的条目。您可以从文件中读取键和值,循环它们并填充字典。

如果您详细说明您正在尝试做什么,我们可以为您提供更具体的建议。

于 2009-10-30T00:20:27.803 回答
1

通过适当的重构(您的假设示例),您可以确保在您的大量案例中,会有很多案例可以使用其字符串参数调用相同的子例程。

在许多这些场景中,您甚至可能不需要巨大的 switch 语句,而只需参数化一个可以处理它们的子例程。

如果没有一个具体的例子来说明你想在案例陈述中做什么,就很难得出一个具体的答案。

于 2009-10-30T00:19:31.440 回答
1

您似乎正在尝试从代码中提取“命令字符串”,以便您可以自动更新用户文档中的可用命令列表。我认为这不会给你带来太多好处,因为你仍然需要手动记录每个命令的作用。

话虽如此,以下powershell命令将从 test.cs 中提取您想要的数据:

type test.cs|select-string 'case "(.*)"'|foreach {$_.Matches[0].Groups[1].Value}
于 2009-10-30T00:53:06.573 回答
0

Switch 语句对常量求值,因此 case 语句不适用于变量。也许您应该考虑使用 Dictionary<> 并基于此进行分支。但是,如果对您正在解决的问题没有任何深入的了解,那么再多说什么也没有意义。

于 2009-10-30T00:21:11.860 回答
0

创建一个抽象类,将其命名为StringHandler. 给它2个抽象方法,1个检查处理程序是否可以处理字符串,然后另一个进行处理。就像是:

  public abstract class StringHandler
  {
    public abstract bool CanProcess(string input);
    public abstract void Process();
  }

  public class HelloStringHandler : StringHandler
  {
    public override bool CanProcess(string input)
    {
      return input.Equals("hello");
    }

    public override void Process()
    {
      Console.WriteLine("HELLO WORLD");
    }
  }

然后在您的主类中,您可以使用所有已知处理程序的列表进行简单循环,例如

  List<StringHandler> handlers = new List<StringHandler>();
  handlers.Add(new HelloStringHandler());
  string myString = "hello";

  foreach (StringHandler handler in handlers)
  {
    if (handler.CanProcess(myString))
    {
      handler.Process();
      break;
    }
  }

所有这些都可以明显优化/改进,但我希望你能明白吗?

于 2009-10-30T00:30:27.210 回答
0

我对 c# 很生疏,但这是一个有趣的小练习。以下代码不是很干净,但会按照您的要求执行。您将希望添加更多检查,更好地使用变量并添加更多逻辑,但这应该有助于您朝着正确的方向前进。

    var newfile = System.IO.File.CreateText("newcode.txt");
    newfile.Write("string[] list = { ");
    using (var file = System.IO.File.OpenText("code.txt"))
    {
        bool bFirst = true;
        while (!file.EndOfStream)
        {
            String line = file.ReadLine();

            if (line.Contains("case ") && line.EndsWith(":"))
            {
                line = line.Replace("case", " ");
                line = line.Replace(":", " ");
                line = line.Trim();
                if (bFirst == false)
                {
                    newfile.Write(", ");
                }
                bFirst = false;
                newfile.Write(line);
            }
        }
    }
    newfile.WriteLine(" };");
    newfile.Close();

祝你好运!

于 2009-10-30T00:41:26.067 回答
0

受@Jheddings 回答的启发,我想出了这个。也许它过分了,但至少我很高兴弄清楚它:

与 jheddings 解决方案相比的主要优点:

  • 使用扩展方法,不需要实用程序类实例。
  • 所有候选方法的反射查找只进行一次,就在评估第一个字符串之前。之后,它是一个简单的查找和调用。
  • 更简单的用法

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Reflection;
    
    namespace StringSwitcher
    { 
    class Program
    {
        static void Main(string[] args)
        {
            "noAction".Execute(); //No action, since no corresponding method defined
            "Hello".Execute();    //Calls Greet method
            "world".Execute();    //Calls Shout method
            "example".Execute();  //Calls Shout method
            Console.ReadKey();
        }
    
        //Handles only one keyword
        [Keywords("Hello")]
        static public void Greet(string s)
        {
            Console.WriteLine(s + " world!");
        }
    
        //Handles multiple keywords
        [Keywords("world", "example")]
        static public void Shout(string s)
        {
            Console.WriteLine(s + "!!");
        }
    }
    
    internal static class ActionBrokerExtensions
    {
        static Dictionary<string, MethodInfo> actions;
    
        static ActionBrokerExtensions()
        {
            //Initialize lookup mechanism once upon first Execute() call
            actions = new Dictionary<string, MethodInfo>();
            //Find out which class is using this extension
            Type type = new StackTrace(2).GetFrame(0).GetMethod().DeclaringType;
            //Get all methods with proper attribute and signature
            var methods = type.GetMethods().Where(
            method => Attribute.GetCustomAttribute(method, typeof(KeywordsAttribute)) is KeywordsAttribute &&
                      method.GetParameters().Length == 1 &&
                      method.GetParameters()[0].ParameterType.Equals(typeof(string)));
            //Fill the dictionary
            foreach (var m in methods)
            {
                var att = (Attribute.GetCustomAttribute(m, typeof(KeywordsAttribute)) as KeywordsAttribute);
                foreach (string str in att.Keywords)
                {
                    actions.Add(str, m);
                }
            }
        }
    
        public static void Execute(this string input)
        {
            //Invoke method registered with keyword 
            MethodInfo mi;
            if (actions.TryGetValue(input, out mi))
            {
                mi.Invoke(null, new[] { input });
            }
        }
    }
    
    [AttributeUsage(AttributeTargets.Method)]
    internal class KeywordsAttribute : Attribute
    {
        private ICollection<string> keywords;
        public KeywordsAttribute(params String[] strings)
        {
            keywords = new List<string>(strings);
        }
    
        public ICollection<string> Keywords
        {
            get { return keywords; }
        }
    }
    

    }

为任何奇怪的渲染道歉,出于某种原因,语法突出显示代码阻塞:-(

于 2009-10-30T02:29:06.317 回答