C#是否支持inout参数?

时间:2013-05-02 07:56:04

标签: c# function parameters out

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

读取每一行都会进行一些测试(例如,以#开头的行是注释,需要跳过),所以我打算将整个阅读过程放在一个函数中,这将保持不变阅读直到遇到有用的行,然后返回该行。如果遇到EOF,则会返回null

当我将此函数定义为string read(StreamReader sr, out int lineNumber)时,我认为我很聪明,但现在事实证明C#将无法在该函数内执行lineNumber++之类的操作。它假定该变量尚未分配,可能是因为它无法知道它是否已在此函数调用之前分配。

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

4 个答案:

答案 0 :(得分:17)

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

另见:When to use ref vs out

答案 1 :(得分:1)

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

来自MSDN - ref (C#)

  

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

答案 2 :(得分:1)

你需要的是

MSDN

  

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

答案 3 :(得分:1)

正如大家所说,你可以简单地使用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()内的优势。 (它不是你班级的成员,因为它是你班级中的一个领域;它只是方法中的一个局部变量。)