关于功能:C#是否支持inout参数?

Does C# support inout parameters?

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

阅读每一行都会伴随一些测试(例如,以#开头的行是注释,需要跳过),因此我计划将整个阅读过程放在一个函数中,它将一直阅读,直到遇到一个有用的行,然后返回该行。如果遇到EOF,它只会返回null

当我把这个函数定义为string read(StreamReader sr, out int lineNumber)时,我认为我很聪明,但现在发现c不能在这个函数内做类似lineNumber++的事情。它假定变量尚未赋值,可能是因为它无法知道是否已在该函数调用之前赋值。

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


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

另请参见:何时使用REF与OUT


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

我建议你换一种方法,让你知道。

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

1
2
3
4
5
public class Line
{
    public string Text;
    public int    Number;
}

然后,您读取行的方法可能如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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};
    }
}

然后您可以使用它,如下所示:

1
2
3
4
5
6
7
8
9
10
public void Test()
{
    StreamReader sr = new StreamReader("Whatever");

    foreach (var line in ReadLines(sr))
    {
        if (line.Text =="SomeSpecialValue")
            doSomethingWith(line.Text, line.Number);
    }
}

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


裁判是你需要的

MSDN

The ref method parameter keyword on a method parameter causes a method
to refer to the same variable that was passed into the method. Any
changes made to the parameter in the method will be reflected in that
variable when control passes back to the calling method.


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

来自msdn-ref(c)

An argument passed to a ref parameter must first be initialized.
Compare this to an out parameter, whose argument does not have to be
explicitly initialized before being passed to an out parameter.