【问题标题】:How to pass const string into function如何将 const 字符串传递给函数
【发布时间】:2022-01-25 04:10:43
【问题描述】:

如何将 const 字符串传递给要在 switch 语句中使用的方法?

上下文

我目前有一个程序可以根据自定义标记解析文件。出于程序的目的,标记是恒定的,但理想情况下可以在运行程序的实例之间更改。我目前对标记进行了硬编码。然后我在几个 switch 语句中使用它们。这很好用。但是,在重构我的代码时,我无法复制该行为,因为我无法将 const 字符串变量传递给函数。虽然我可以在方法中对声明进行硬编码,但由于显而易见的原因,这既不理想也不实用。

我试过了

  1. 将变量作为 ref 传递给原始 const 变量: Method(ref string keyIndicator)
  2. 使用“in”关键字传递变量: Method(in string keyIndicator)
  3. 基于以上两个重新声明变量常量: Method(ref string keyIndicator)Method(in string keyIndicator) 后跟: const string kIndicator = keyIndicator;

切线

无论我做什么,我都会得到一个错误:

分配给“x”的表达式必须是常量。

但它是不变的。 作为一个附带问题,为什么我不能在逻辑上将一个常量分配给一个变量(听我说),这样在初始化时,常量字符串就被设置为程序的生命周期?例如:

在程序运行时,程序会询问用户的姓名,然后将该值存储在一个常量变量中。

const string hi = Console.ReadLine();

TLDR

我需要为我的 switch 语句使用变量,我已经通过硬编码一个常量变量来做到这一点。但是,我正在尝试重构我的代码,并将这些 switch 语句移动到方法中,据我所知,这将不允许我传递常量变量。我知道我一定遗漏了一些东西,因为肯定不会对他们所有的开关选择进行硬编码,而且他们肯定会在方法中使用开关。那么,帮助一个陷入困境的初学者吗?

由于请求代码...

原始代码(粗略地说,我不得不稍微调整一下以模拟它在我的程序上下文中的样子)。我比以往任何时候都更加困惑,因为在尝试缩减代码以放置在这里时,它实际上确实有效。但仅在辅助文件中。我将代码复制回我的程序,但它没有。 >:/.

工作测试文件创建以显示我正在尝试做的事情...

    internal class Program{
    static void Main(string[] args)
    {
        string fileToParse = "!--------------------Demo Key@--------------------DemoBody#--------------------DemoClinical";
        //
        //
        //!!!!!Set Constants for Deliniators!!!!
        //
        //
        const string divider = "--------------------";
        const string keySign = "!";
        const string bodySign = "@";
        const string clinicalSign = "#";
        //
        //
        //!!!!!Set Constants for Deliniators!!!!
        //
        //
        const string keyIndicator = keySign + divider;
        const string bodyIndicator = bodySign + divider;
        const string clinicalIndicator = clinicalSign + divider;
        //
        //
        List<String> checkDeliniators = new List<String>();
        checkDeliniators.Add(keyIndicator);
        checkDeliniators.Add(bodyIndicator);
        checkDeliniators.Add(clinicalIndicator);

        SetIndexes(ref fileToParse, checkDeliniators);


        static void SetIndexes(ref string fileToParse, List<string> checkDeliniators)
        {

            //Create Lists of indexes (Starts and Stops for Text desired)
            foreach (var indicator in checkDeliniators)
            {
                int index = 0;
                while ((fileToParse.IndexOf(indicator, index)) != -1)
                {
                    index = fileToParse.IndexOf(indicator, index);      //  (Undesired text"!"------Desired text)
                    index = index + indicator.Length;                   //  (Undesired text!-------""Desired text)  

                    //assigns this index to the appropriate list
                    switch (indicator)
                    {
                        case keyIndicator:
                            Console.WriteLine("Key start {0}", index);
                            break;
                        case bodyIndicator:
                            Console.WriteLine("body start {0}", index);
                            break;
                        case clinicalIndicator:
                            Console.WriteLine("clinical start {0}", index);
                            break;
                        default:
                            // Do this;
                            break;
                    }

                    //sets END of Text 
                    if ((fileToParse.IndexOf(divider, index)) != -1) //(if there are more instances of divider, move index forward)
                    {
                        //indexed moved forward to next divider, and then backed up to desired text END.
                        index = fileToParse.IndexOf(divider, index);    //  (!"-"------) (diver used because next Indicator not predictable)
                        index = index - keySign.Length;                 //  ("!"-------) (Recall end index is not inclusive)

                        switch (indicator)  //refers to prior indicator (end), not next indicator (start)
                        {
                            case keyIndicator:
                                Console.WriteLine("Key end {0}", index);
                                break;
                            case bodyIndicator:
                                Console.WriteLine("body end {0}", index);
                                break;
                            case clinicalIndicator:
                                Console.WriteLine("clinical end {0}", index);
                                break;
                            default:
                                // Do this;
                                break;
                        }
                        index++; // (!"-"-------)  Technically shouldn't be necessary, but just incase search for divider in future...
                    }
                    else //else, if there are no more instances of divider, leave the index alone, and set the end of text to end of file
                    {
                        index = fileToParse.Length;
                        switch (indicator)
                        {
                            case keyIndicator:
                                Console.WriteLine("Key end {0}", index);
                                break;
                            case bodyIndicator:
                                Console.WriteLine("body end {0}", index);
                                break;
                            case clinicalIndicator:
                                Console.WriteLine("clinical end {0}", index);
                                break;
                            default:
                                // Do that;
                                break;
                        }
                    }
                }
            }
        }
    }
}

带输出运行

Key start 21
Key end 29
body start 50
body end 58
clinical start 79
clinical end 91

虽然代码相同:

    //
    //
    //!!!!!Set Constants for Deliniators!!!!
    //
    //
    const string divider = "--------------------";
    const string keySign = "!";
    const string bodySign = "@";
    const string clinicalSign = "#";
    //
    //
    //!!!!!Set Constants for Deliniators!!!!
    //
    //
    const string keyIndicator = keySign + divider;
    const string bodyIndicator = bodySign + divider;
    const string clinicalIndicator = clinicalSign + divider;
    //
    //
    List<String> checkDeliniators = new List<String>();
    checkDeliniators.Add(keyIndicator);
    checkDeliniators.Add(bodyIndicator);
    checkDeliniators.Add(clinicalIndicator);


    List<String> KeyList = new List<String>();
    List<String> BodyList = new List<String>();
    List<String> ClinicalList = new List<String>();
    List<String> GarbageList = new List<String>();

    List<int> keyStartIndex = new List<int>();
    List<int> bodyStartIndex = new List<int>();
    List<int> clinicalStartIndex = new List<int>();
    List<int> garbageStartIndex = new List<int>();

    List<int> keyEndIndex = new List<int>();
    List<int> bodyEndIndex = new List<int>();
    List<int> clinicalEndIndex = new List<int>();
    List<int> garbageEndIndex = new List<int>();




    
    const string fileSign = "|";
    //const string commentSign = "~";
    //const string allIndicators = keySign + bodySign + clinicalSign;

    string fileStartIndicator = fileSign + divider;
    string fileEndIndicator = divider + fileSign;



    bool headerSet = SetHeader(ref fileToParse, fileStartIndicator, ref fileHeader);
    bool footerSet = SetFooter(ref fileToParse, fileEndIndicator, ref fileFooter);
    SetIndexes(ref fileToParse, checkDeliniators);

    static void SetIndexes(ref string fileToParse, List<string> checkDeliniators)
    {
        //Create Lists of indexes (Starts and Stops for Text desired)
        foreach (var indicator in checkDeliniators)
        {
            int index = 0;
            while ((fileToParse.IndexOf(indicator, index)) != -1)
            {
                index = fileToParse.IndexOf(indicator, index);      //  (Undesired text"!"------Desired text)
                index = index + indicator.Length;                   //  (Undesired text!-------""Desired text)  

                //assigns this index to the appropriate list
                switch (indicator)
                {
                    case keyIndicator:
                        keyStartIndex.Add(index);
                        break;
                    case bodyIndicator:
                        bodyStartIndex.Add(index);
                        break;
                    case clinicalIndicator:
                        clinicalStartIndex.Add(index);
                        break;
                    default:
                        garbageStartIndex.Add(index);
                        break;
                }

                //sets END of Text 
                if ((fileToParse.IndexOf(divider, index)) != -1) //(if there are more instances of divider, move index forward)
                {
                    //indexed moved forward to next divider, and then backed up to desired text END.
                    index = fileToParse.IndexOf(divider, index);    //  (!"-"------) (diver used because next Indicator not predictable)
                    index = index - keySign.Length;                 //  ("!"-------) (Recall end index is not inclusive)

                    switch (indicator)  //refers to prior indicator (end), not next indicator (start)
                    {
                        case keyIndicator:
                            keyEndIndex.Add(index);
                            break;
                        case bodyIndicator:
                            bodyEndIndex.Add(index);
                            break;
                        case clinicalIndicator:
                            clinicalEndIndex.Add(index);
                            break;
                        default:
                            garbageEndIndex.Add(index);
                            break;
                    }
                    index++; // (!"-"-------)  Technically shouldn't be necessary, but just incase search for divider in future...
                }
                else //else, if there are no more instances of divider, leave the index alone, and set the end of text to end of file
                {
                    index = fileToParse.Length;
                    switch (indicator)
                    {
                        case keyIndicator:
                            keyEndIndex.Add(index);
                            break;
                        case bodyIndicator:
                            bodyEndIndex.Add(index);
                            break;
                        case clinicalIndicator:
                            clinicalEndIndex.Add(index);
                            break;
                        default:
                            garbageEndIndex.Add(index);
                            break;
                    }
                }
            }
        }
    }

告诉我指标(即“keyIndi​​cator”)需要保持不变的错误。

【问题讨论】:

  • tldr;写代码,或者分享你写的代码。
  • ReadLine 不返回常量。它每次返回不同的值。
  • 根据定义,常量是在程序编译时确定的。它不能是程序运行时确定的任何东西。如果您有一个字符串,但它可能是一个字符串或可能是不同的字符串,它必须是一个变量。它是变化的,所以它是一个变量。
  • 您似乎认为 C# 中的 const 与 C++ 中的 const 一样。它不是。 C# 中的 readonly 更接近于 C++ const。 C# 中的 const 类似于 C++ #defineconstexpr
  • 为什么不能使用对编译时间常数没有任何限制的if()

标签: c# switch-statement constants


【解决方案1】:

在我上面的代码中,有一个有效,一个无效,尽管代码相同。

**

解决方案是一个 Method 嵌套在 Main() {} 中。而另一个在它之外。

**

将代码移动到 Main() 允许在那里声明的 const 变量传递到方法中,并且代码按预期运行。我仍然不确定如何在命名空间或 main 之外传递 const ......但目前这是我的问题。因此,对于所有像我这样喜欢在非文字情况下使用 switch 语句的人......好了。

我等待知识和进一步的澄清:)。

【讨论】:

    【解决方案2】:

    在 switch 语句的标签中只能使用文字或常量。大多数语言的语法都是以这种方式指定的。如果您需要打开变量,请将您的 switch 语句替换为 if-else 语句。

    var x = …;
    var y = …;
    switch (z) {
      case x: doX(); break;
      case y: doY(); break;
      default: doOther(); break;
    }
    

    变成

    var x = …;
    var y = …;
    if (z == x) {
      doX();
    } else if (z == y) {
      doY();
    } else {
      doOther();
    }
    

    【讨论】:

    • 可能是最有帮助的回应,所以得到我的支持。但公平地说,并没有真正回答这个问题。问题是为什么我无法将 const 传递给方法。我已经在使用变量(请注意)来运行我的 switch 语句。 (这样 const 就可以在程序开始时声明,而不必在以后挖掘代码来更新“”......但是,当我重构我的代码时,将我的循环/开关从 Main 中取出,并且把它放在一个单独的方法中,它坏了。所有改变的是它从 main() 中移出。把它放回去修复它。那么给出了什么?
    • @SilentKnight 我不知道。该问题最初不包含任何代码。您的表达式 x 不是常量,因此您不能将其用作开关标签。如果不能将其设为常量,则不能在 switch 语句中使用它。 “常量”只是用关键字const 声明的东西。
    猜你喜欢
    • 2021-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-28
    相关资源
    最近更新 更多