Подтвердить что ты не робот

Поддерживает ли С# inout параметры?

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

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

Из MSDN - ref (С#)

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

Ответ 3

Ссылка - это то, что вам нужно

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