C# 需要在C中创建大型switch语句的摘要
好吧,我不知道该怎么解释。。但我有一个切换语句C# 需要在C中创建大型switch语句的摘要,c#,switch-statement,summary,C#,Switch Statement,Summary,好吧,我不知道该怎么解释。。但我有一个切换语句 string mystring = "hello"; switch(mystring) { case "hello": break; case "goodbye": break; case "example": break; } 当然,这是一个例子,在实际情况中,每种情况都会发生不同的事情。 好吧,希望你明白了,现在,手动操作是不可能的,因为不同案例的数量太多了。我需要分别创建一个所有案例的列表,例如。。对于上面的switch语句,我需要 str
string mystring = "hello";
switch(mystring)
{
case "hello":
break;
case "goodbye":
break;
case "example":
break;
}
当然,这是一个例子,在实际情况中,每种情况都会发生不同的事情。
好吧,希望你明白了,现在,手动操作是不可能的,因为不同案例的数量太多了。我需要分别创建一个所有案例的列表,例如。。对于上面的switch语句,我需要
string[] list = { "hello", "goodbye", "example" };
也许可以和一个老师一起做一些我不知道的事情,任何帮助都将不胜感激
此外,提供的任何工作代码都将非常棒
编辑:
人们要求更多的细节,下面是它的工作原理。
程序的用户输入一系列字符串。
根据他们输入的字符串,它将执行一些if's和else if's并基本上返回新字符串。我需要能够创建一个列表,通过该计划,所有可用的选项使用。我不能只是列出一个清单,然后硬编码,因为我总是在陈述中添加更多的事例,我也不能回去更新清单。这取决于你想要多聪明。。。您可以创建一个自定义属性,该属性使用该方法应处理的字符串附加到方法。然后,您只需找到具有所需值的属性并执行它,而不是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属性
编辑此项还有一个额外的好处,即可以通过删除循环逻辑中的中断来定义作用于同一字符串的多个方法。这取决于您希望获得的智能程度。。。您可以创建一个自定义属性,该属性使用该方法应处理的字符串附加到方法。然后,您只需找到具有所需值的属性并执行它,而不是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属性
编辑此项还有一个额外的好处,即您可以通过删除循环中的中断逻辑来定义作用于同一字符串的多个方法。通过适当重构您的假设示例,您可以确保在您的大量案例中,有许多案例可以使用其字符串参数调用同一子例程 在许多这样的场景中,您甚至可能不需要一个巨大的switch语句,只需参数化一个子例程即可处理它们
如果没有一个具体的例子来说明你想在case语句中做什么,就很难给出一个具体的答案。通过适当地重构你假设的例子,你可以确保在你大量的案例中,有很多案例可以用它们的字符串参数调用相同的子例程 在许多这样的场景中,您甚至可能不需要一个巨大的switch语句,只需参数化一个子例程即可处理它们
如果没有一个具体的例子来说明你想在案例陈述中做什么,就很难给出一个具体的答案。我肯定你想做什么,但你可能会使用字典
Dictionary<string, int> lookupTable = new Dictionary<string, int>();
lookupTable.Add("hello", 1);
lookupTable.Add("goodbye", 2);
lookupTable.Add("example", 3);
int output = lookupTable["hello"];
您不需要使用代码来添加每个条目。您可以从文件中读入键和值,循环它们并填充字典
如果你能详细解释你想做什么,我们可以给你更具体的建议。我肯定你想做什么,但你可能会使用字典
Dictionary<string, int> lookupTable = new Dictionary<string, int>();
lookupTable.Add("hello", 1);
lookupTable.Add("goodbye", 2);
lookupTable.Add("example", 3);
int output = lookupTable["hello"];
您不需要使用代码来添加每个条目。您可以从文件中读入键和值,循环它们并填充字典
如果您详细解释您正在尝试执行的操作,我们可以给您提供更具体的建议。Switch语句对常量求值,因此case语句对变量不起作用。也许你应该考虑使用字典和分支的基础上。但是,如果对您正在解决的问题没有更多的了解,那么再多说就没有什么意义了。Switch语句对常量求值,因此case语句对变量不起作用。也许你应该考虑使用字典和分支的基础上。但是,如果对您正在解决的问题没有更多的了解,那么再多说就没有什么意义了。对于VISUAL STUDIO: 如果mystrin g是一个枚举而不是字符串,在visual studio中,如果键入switch[TAB]mystring[ENTER],它将为您构建一个包含所有案例的长开关。对于visual studio:
如果mystring是一个枚举而不是字符串,那么在visual studio中,如果键入switch[TAB]mystring[ENTER],它将为您构建一个包含所有情况的长开关。创建一个抽象类,将其称为类似StringHandler的类。给它两个抽象方法,一个用于检查处理程序是否可以处理字符串,另一个用于处理。比如:
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;
}
}
显然,所有这些都可以得到优化/改进,但我希望您能理解这一点。创建一个抽象类,称之为StringHandler之类的东西。给它两个抽象方法,一个用于检查处理程序是否可以处理字符串,另一个用于处理。比如:
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;
}
}
显然,所有这些都可以得到优化/改进,但我希望你明白了吗?我对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();
祝你好运 我对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();
祝你好运 您似乎试图从代码中提取命令字符串,以便可以自动更新用户文档中可用命令的列表。我认为这不会给您带来太多好处,因为您仍然需要手动记录每个命令的作用 也就是说,以下命令将从test.cs中提取所需的数据:
type test.cs|select-string 'case "(.*)"'|foreach {$_.Matches[0].Groups[1].Value}
您似乎试图从代码中提取命令字符串,以便可以自动更新用户文档中可用命令的列表。我认为这不会给您带来太多好处,因为您仍然需要手动记录每个命令的作用 也就是说,以下命令将从test.cs中提取所需的数据:
type test.cs|select-string 'case "(.*)"'|foreach {$_.Matches[0].Groups[1].Value}
受@Jheddings answer的启发,我想到了这个。也许这有点过头了,但至少我很开心地发现了这一点: 与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; }
}
}
}
对于任何奇怪的呈现,我深表歉意,因为某些原因,语法突出显示会阻塞代码:-受@Jheddings answer的启发,我想到了这个。也许这有点过头了,但至少我很开心地发现了这一点: 与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; }
}
}
}
对于任何奇怪的呈现表示歉意,由于某些原因,语法高亮显示会阻塞代码:-在每个case语句中,您将如何处理这些字符串?我不认为这是最好的解决方案,但需要了解您使用这些字符串的目的。您的代码似乎没有任何作用!当然,如果您的输入字符串列表是动态的,并且您无法维护它,那么您的if和else if也需要更改吗?如果不是,这意味着有一种预定义的方法来处理任何输入字符串,在这种情况下不需要开关。那么,程序的目的是以对话的方式响应吗?i、 e.用户输入hello并回复再见?至少对我来说,你的细节不够清晰。在每个case语句中,你将如何处理这些字符串?我不认为这是最好的解决方案,但需要了解您使用这些字符串的目的。您的代码似乎没有任何作用!当然,如果您的输入字符串列表是动态的,并且您无法维护它,那么您的if和else if也需要更改吗?如果不是,这意味着有一种预定义的方法来处理任何输入字符串,在这种情况下不需要开关。那么,程序的目的是以对话的方式响应吗?i、 e.用户输入hello并回复再见?至少对我来说,您的详细信息没有增加足够的清晰度。您需要首先了解原始代码的目的是什么。这可能是因为完全不需要切换。就像使用自定义属性的方法一样,但我对性能有疑问。由于这涉及到反射,它可能会变得非常缓慢。如果性能不是问题
不过,这是一个相当优雅的解决方案。受此答案的启发,我实现了另一个解决方案。请看我的答案。您需要首先了解原始代码的目的是什么。这可能是因为完全不需要切换。就像使用自定义属性的方法一样,但我对性能有疑问。由于这涉及到反射,它可能会变得非常缓慢。如果性能不是问题的话,这是一个非常优雅的解决方案。受这个答案的启发,我实现了另一个解决方案。请看我的答案。不过,这仍然需要完整的switch语句,而OP正试图避免这种情况。不过,这仍然需要完整的switch语句,OP试图避免的操作。如果将列表更改为字典,则可以将查找留给字典,只需执行为指定键添加的操作委托。若要查看我的其他注释示例,请参阅我的答案,它不使用操作,但字典部分类似。如果将列表更改为字典,则可以将查找留给字典,只需执行为指定键添加的操作委托。要查看我的其他注释示例,请参阅我的答案,它不使用操作,但字典部分类似。