Поддерживает ли C# входные параметры?

В C# я использую StreamReader читать файл, строка за строкой. Я также держу номер текущей строки в int, для сообщений о возможных сообщениях об ошибках.

Чтение каждой строки сопровождается некоторыми тестами (например, строки, начинающиеся с # комментарии, и их нужно пропустить), поэтому я планирую поместить всю процедуру чтения в функцию, которая будет продолжать чтение до тех пор, пока не встретит полезную строку, а затем вернет эту строку. Если это сталкивается EOF это просто вернется null,

Я думал, что был умным, когда я определил эту функцию как string read(StreamReader sr, out int lineNumber), но теперь получается, что C# не сможет сделать что-то вроде lineNumber++ внутри этой функции. Предполагается, что переменная еще не была назначена, возможно потому, что у нее нет способа узнать, была ли она назначена до вызова этой функции.

Итак, проблема проста: как я могу указать, что эта переменная inout параметр (я думаю, что это термин; я слышал, что он упоминается в контексте других языков программирования)? Это вообще возможно в первую очередь? Я абсолютно не собираюсь делать lineNumber член моего класса, так что это не вариант.

4 ответа

Решение

В этом случае вам нужно ref параметр вместо out, С out ключевое слово, ответственность за назначение / создание значения лежит в вызывающем вызываемом методе; с ref он лежит вне вызываемого метода.

Также смотрите: Когда использовать ref vs out

Реф это то что тебе нужно

MSDN

Ключевое слово параметра метода ref в параметре метода заставляет метод ссылаться на ту же переменную, которая была передана в метод. Любые изменения, внесенные в параметр в методе, будут отражены в этой переменной, когда управление вернется к вызывающему методу.

Используйте ключевое слово ref вместо out. Это заставит звонящего инициализировать аргумент перед вызовом.

Из MSDN - ссылка (C#)

Аргумент, передаваемый параметру ref, должен сначала быть инициализирован. Сравните это с параметром out, чей аргумент не нужно явно инициализировать перед передачей в параметр out.

Как все говорят, вы можете просто использовать 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(), (Это не член вашего класса в том смысле, что это поле в вашем классе; это просто локальная переменная в методе.)

Другие вопросы по тегам