【问题标题】:Does C# support inout parameters?C# 是否支持 inout 参数?
【发布时间】:2013-04-26 07:52:49
【问题描述】:

在 C# 中,我使用StreamReader 来读取文件,每行一行。我还将当前行的编号保存在 int 中,以报告可能的错误消息。

阅读每一行都伴随着一些测试(例如,以#开头的行是cmets,需要跳过),所以我打算将整个阅读过程放在一个函数中,它会一直阅读直到它遇到一个有用的行,然后返回该行。如果遇到EOF,它将简单地返回null

当我将此函数定义为string read(StreamReader sr, out int lineNumber) 时,我认为我很聪明,但现在事实证明,C# 将无法在该函数中执行类似lineNumber++ 的操作。它假设变量还没有被赋值,可能是因为在这个函数调用之前它无法知道它是否已经被赋值。

所以,问题很简单:我如何指定这个变量是inout 参数(我认为这是术语;我听说它在其他编程语言的上下文中被提及)?这甚至可能吗? 我绝对不会让lineNumber 成为我班级的成员,所以这不是一个选择。

【问题讨论】:

标签: c# function parameters out


【解决方案1】:

在这种情况下,您需要ref 参数而不是out。使用 out 关键字,分配/实例化值的责任在于 calling 被调用的方法;对于ref,它位于被调用的方法之外。

另见:When to use ref vs out

【讨论】:

    【解决方案2】:

    使用 ref 关键字代替 out。这将强制调用者在调用之前初始化参数。

    来自MSDN - ref (C#)

    必须首先初始化传递给 ref 参数的参数。 将此与 out 参数进行比较,其参数不必是 在传递给 out 参数之前显式初始化。

    【讨论】:

      【解决方案3】:

      你需要一个 ref

      MSDN

      方法参数上的ref方法参数关键字导致方法 引用传递给方法的相同变量。任何 对方法中的参数所做的更改将反映在 控制权传递回调用方法时的变量。

      【讨论】:

        【解决方案4】:

        正如大家所说,你可以简单地使用ref

        我将建议一种替代方法,以便您了解它。

        您可以编写一个返回IEnumerable<Line> 的方法,其中Line 是一个非常简单的类,它只封装了一行文本和一个行号:

        public class Line
        {
            public string Text;
            public int    Number;
        }
        

        那么您读取这些行的方法可能如下所示:

        public IEnumerable<Line> ReadLines(StreamReader sr)
        {
            int number = 0;
        
            while (true)
            {
                string line = sr.ReadLine();
        
                if (line == null)
                    break;
        
                ++number;
        
                if (wantLine(line)) // Some predicate which decides if you want to keep the line.
                    yield return new Line{Text = line, Number = number};
            }
        }
        

        那么你可以如下使用它:

        public void Test()
        {
            StreamReader sr = new StreamReader("Whatever");
        
            foreach (var line in ReadLines(sr))
            {
                if (line.Text == "SomeSpecialValue")
                    doSomethingWith(line.Text, line.Number);
            }
        }
        

        这需要写更多的工作,但我认为它可以使代码更清晰,并且它还有一个优点是行号计数器完全隐藏在ReadLines()中。 (它不是类的成员,因为它是类中的一个字段;它只是方法中的一个局部变量。)

        【讨论】:

          猜你喜欢
          • 2012-02-29
          • 1970-01-01
          • 2012-03-20
          • 2011-04-16
          • 2013-10-08
          • 2010-12-09
          • 2023-03-25
          • 2010-12-15
          相关资源
          最近更新 更多