C# 在C语言中使用模式匹配选择合适的方法#

C# 在C语言中使用模式匹配选择合适的方法#,c#,asp.net,.net,pattern-matching,C#,Asp.net,.net,Pattern Matching,目前我正在做一个C#的大学项目,其中包括将一种形式的代码转换为另一种形式的代码,包括从许多可用的方法中选择合适的方法/函数。这里的问题是,使用任何模式匹配技术来实现这一点,而不是使用许多IF-ELSE语句 现在,我已经使用嵌套的IF-ELSE语句实现了这一点,它填充了整个程序,看起来像是完成时的幼稚代码 目前的执行情况:-- 输入: //stored in list<string> get(3 int) //type1 get(int:a,b,c) //type2 get

目前我正在做一个C#的大学项目,其中包括将一种形式的代码转换为另一种形式的代码,包括从许多可用的方法中选择合适的方法/函数。这里的问题是,使用任何模式匹配技术来实现这一点,而不是使用许多IF-ELSE语句

现在,我已经使用嵌套的IF-ELSE语句实现了这一点,它填充了整个程序,看起来像是完成时的幼稚代码

目前的执行情况:--

输入:

//stored in list<string>
get(3 int)      //type1
get(int:a,b,c)  //type2
get(name)       //type3
//list passed to ProcessGET method
//存储在列表中
get(3 int)//type1
get(int:a,b,c)//type2
get(name)//type3
//传递给ProcessGET方法的列表
使用if-else:

public string ProcessGET(List<string> inputData)
{
      foreach(var item in inputData)
      { 
         if (inputData.item.Split('(')[1].Split(')')[0].Contains(':'))
         {
            return Type2 result;
         }
         else if (!inputData.item.Split('(')[1].Split(')')[0].Contains(':') && Convert.ToInt32(inputData.item.Split('(')[1].Split(')')[0].Split(' ')[0])>0)
         {
            return Type1 result;
         }
         else
         {
            return Type3 result;
         }
      }   
}
公共字符串ProcessGET(列出inputData)
{
foreach(inputData中的var项)
{ 
如果(inputData.item.Split(“(”)[1]。Split(“)”)[0]。包含(“:”)
{
返回Type2结果;
}
如果(!inputData.item.Split('(')[1].Split(')')[0]。包含(':')和转换.ToInt32(inputData.item.Split('(')[1].Split('))[0].Split('[0])>0,则为else
{
返回Type1结果;
}
其他的
{
返回Type3结果;
}
}   
}
我想要的是这样的

/stored in list<string>
get(3 int)      //type1
get(int:a,b,c)  //type2
get(name)       //type3
//list passed to ProcessGET method


public string ProcessGET(List<string> inputData)
{
      foreach(var itm in inputData)
      { 
        // call appropriate method(itm) based on type using some pattern matching techniques
      }   
}

string Method1(var data)
{
    return result for type1;  
}   
string Method2(var data)
{
    return result for type2;  
}
string Method3(var data)
{
    return result for type3;  
}
/存储在列表中
get(3 int)//type1
get(int:a,b,c)//type2
get(name)//type3
//传递给ProcessGET方法的列表
公共字符串ProcessGET(列表inputData)
{
foreach(输入数据中的var itm)
{ 
//使用一些模式匹配技术基于类型调用适当的方法(itm)
}   
}
字符串方法1(变量数据)
{
返回type1的结果;
}   
字符串方法2(变量数据)
{
返回type2的结果;
}
字符串方法3(变量数据)
{
返回type3的结果;
}
通常,我的程序主要针对各种类型的输入关键字(如“get”、“output”、“declare”等)执行此类工作。。。其中Get转换为Scanf语句,输出为printf语句,等等。 在这种情况下,如果我使用if-ELSE,我的项目将充满if-ELSE语句

由于我刚开始学习C#,我不知道是否存在这样的东西(谷歌搜索,但没有找到我要找的东西),所以任何关于这个问题的帮助都将对进一步的开发非常有帮助(有用)


非常感谢。

我会在这里留下一些建议,供您参考。下面是一些基本代码

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace TestStuff
{
    class Program
    {
        //Input string should be of the form "<type>:<index>"
        static dynamic GiveMeSomethingDynamic(string someInput)
        {
            /* predefined arrays sothat we can return something */
            string[] _storedStrings = { "Word 1", "word 2", "word 3" };
            int[] _storedInts = { 1, 2, 3 };
            float[] _storedFloats = { 3.14f, 2.71f, 42.123f };

            /* Parse the input command (stringly typed functions are bad, I know.) */
            string[] splitted = someInput.Split(':');
            string wantedType = splitted[0];
            int index = int.Parse(splitted[1]);

            /* Decide what to return base on that argument */
            switch (wantedType)
            {
                case "int":
                    return _storedInts[index];
                case "string":
                    return _storedStrings[index];
                case "float":
                    return _storedFloats[index];

                //Nothing matched? return null
                default:
                    return null;
            }
        }

        static void Main(string[] args)
        {
            /* get some return values */
            dynamic firstOutput = GiveMeSomethingDynamic("string:0");
            dynamic secondOutput = GiveMeSomethingDynamic("int:1");
            dynamic thirdOutput = GiveMeSomethingDynamic("float:2");

            /* Display the returned objects and their type using reflection */
            Console.WriteLine("Displaying returned objects.\n" +
                              "Object 1: {0}\t(Type: {1})\n" +
                              "Object 2: {2}\t\t(Type: {3})\n" +
                              "Object 3: {4}\t\t(Type: {5})\n",
                              firstOutput, firstOutput.GetType(),
                              secondOutput, secondOutput.GetType(),
                              thirdOutput, thirdOutput.GetType());

            /* Act on the type of a object. This works for *all* C# objects, not just dynamic ones. */
            if (firstOutput is string)
            {
                //This was a string! Give it to a method which needs a string
                var firstOutputString = firstOutput as string; //Cast it. the "as" casting returns null if it couldn't be casted.
                Console.WriteLine("Detected string output.");
                Console.WriteLine(firstOutputString.Substring(0, 4));
            }

            //Another test with reflection. 
            Console.WriteLine();

            //The list of objects we want to do something with
            string[] values = { "string:abcdef", "int:12", "float:3.14" };
            foreach(var value in values)
            {
                /* Parse the type */
                string[] parsed = value.Split(':');
                string _type = parsed[0];
                string _argument = parsed[1];

                switch (_type)
                {
                    case "string":
                        //This is a string.
                        string _stringArgument = _argument as string;
                        Method1(_stringArgument);
                        break;
                    case "int":
                        //Do something with this int
                        int _intArgument = int.Parse(_argument);
                        Method2(_intArgument);
                        break;
                    case "float":
                        float _floatArgument = float.Parse(_argument);
                        Method3(_floatArgument);
                        break;

                    default:
                        Console.WriteLine("Unrecognized value type \"{0}\"!", _type);
                        break;
                }

            }


            Console.ReadLine();
        }

        public static void Method1(string s) => Console.WriteLine("String Function called with argument \"{0}\"", s);
        public static void Method2(int i) => Console.WriteLine("int Function called with argument {0}", i);
        public static void Method3(float f) => Console.WriteLine("float Function called with argument {0}", f);
    }
}
“老派”方法(不使用
dynamic
)只将
对象
类型传递到每个函数中,但解析是等效的(
if(someArgument.GetType()==typeof(string))
…)


希望本文能为您提供一些有关如何解析这些字符串、将它们转换为不同类型以及使用它调用不同函数的想法。

因此这些类型将作为字符串存储在列表中,对吗?您想根据字符串的值调用不同的函数吗

下面是我将如何完成您的代码:

  • 创建一个接口:

    public interface IMyType 
            {
                string Result(); 
                string Input {get; set;}
    
            }
    
  • 以及实现它的三个类:

     public class Type1 : IMyType
        {
            public string Result()
            {
                // do something
            }
            public string Input {get; set;}
    
    
        }
    
    (对类型2和类型3重复此操作)

  • 3.然后创建一个返回这三种类型之一的方法 基于匹配字符串输入的模式

        public IMyType GetAppropriateType(string input)
        { 
        if (inputData.item.Split('(')[1].Split(')')[0].Contains(':'))
                 {
                    return new Type2 {Input = input};
                 }
        //etc
        }
    
        public string ProcessGET(List<string> inputData)
        {
              foreach(var itm in inputData)
              { 
                 IMyType type = GetAppropriateType(itm);
                 type.Result();
    
              }   
        }
    
    public IMyType getpropertype(字符串输入)
    { 
    如果(inputData.item.Split(“(”)[1]。Split(“)”)[0]。包含(“:”)
    {
    返回新的Type2{Input=Input};
    }
    //等
    }
    公共字符串ProcessGET(列表inputData)
    {
    foreach(输入数据中的var itm)
    { 
    IMyType type=getpropertype(itm);
    type.Result();
    }   
    }
    

    可能也值得为字符串匹配查看正则表达式

    解决此问题的另一个通用方法是引入一个接口,例如
    IMatcher
    。该接口有一个方法
    Match
    ,该方法返回您的类型或完全转换的行

    您可以创建多个实现
    IMatcher
    的类

    然后,主循环变为:

    var matchers = new [] { new MatcherA(), new MatcherB(), ... };
    
    foreach (string line in input)
      foreach (matcher in matchers)
      {
         var match = matcher.Match(line);
         if (match != null) return match;
      }
    

    没有更大的if语句。每个matcher都有自己的小类,您可以为每个类编写单元测试。另外,使用正则表达式可以简化匹配程序。

    您能告诉我们您的实际代码吗<类型3(var数据)的代码>函数无效。我也很难理解你所说的
    get(3int)
    。您在谈论重载吗?
    动态
    关键字作为返回类型允许您返回任意值。然后,您可以使用
    typeof
    操作符检查返回内容的类型,也许可以尝试深入研究该材料,看看是否可以在您的案例中使用它。(
    public dynamic ProcessGET()
    然后可以返回
    Type1
    Type2
    Type3
    对象,没有问题。)@Rob这些get()输入方法是我自己的自定义语法。@MaximilianGerhardt-如果我的意思不正确,很抱歉。实际上,我总是从所有方法返回字符串值。转换代码的更好方法是构建(或使用现有的)解析器,该解析器在内存中构建抽象语法树,然后使用语法树上的“访问者模式”将其转换为所选输出。这可能超出了本项目的范围,但值得阅读这些概念,以了解解决问题的更好方法。感谢您的解决方案。我认为,与直接使用“IF-ELSE”语句相比,这种方法绝不会减少“IF”语句的数量,但它将有助于隐藏“IF”语句的大量使用。ProcessGET()方法的foreach(…)循环中的3个条件检查语句(IF、IF-ELSE、ELSE)被移动到单独的方法中,在该方法中执行相同的操作。但是,正如我所说,它有助于隐藏/分离这些条件语句。感谢您提供了许多有用的附加信息。我想知道我是否能使用这些动态类型是的,这会减少。我会试试
    var matchers = new [] { new MatcherA(), new MatcherB(), ... };
    
    foreach (string line in input)
      foreach (matcher in matchers)
      {
         var match = matcher.Match(line);
         if (match != null) return match;
      }