Поддержка ссылочных возвращаемых значений (Visual Basic)

Язык C# поддерживает ссылочные возвращаемые значения. Один из способов понять значения возвращаемых ссылок заключается в том, что они являются противоположностью аргументов, передаваемых по ссылке на метод. При изменении аргумента, передаваемого по ссылке, изменения отражаются в значении переменной вызывающего объекта. Когда метод предоставляет вызывающему объекту возвращаемое значение ссылки, изменения, внесенные в возвращаемое значение вызывающего объекта, отражаются в данных вызываемого метода.

Visual Basic не позволяет создавать методы с ссылочными возвращаемыми значениями, но позволяет использовать значения возвращаемых ссылок. Другими словами, можно вызвать метод с ссылочным возвращаемым значением и изменить это возвращаемое значение, а изменения ссылочного возвращаемого значения отражаются в данных вызываемого метода.

Изменение возвращаемого значения ссылки напрямую

Для методов, которые всегда успешно и не ByRef имеют параметров, можно напрямую изменить возвращаемое значение ссылки. Для этого необходимо назначить новое значение выражениям, возвращающим возвращаемое значение ссылки.

В следующем примере C# определяется NumericValue.IncrementValue метод, который увеличивает внутреннее значение и возвращает его в качестве возвращаемого значения ссылки.

using System;

public class NumericValue
{
   private int value = 0;

   public NumericValue(int value)
   {
      this.value = value;
   }

   public ref int IncrementValue()
   {
      value++;
      return ref value;
   }

   public int GetValue()
   {
      return value;
   }
}

Затем возвращаемое значение ссылки изменяется вызывающим элементом в следующем примере Visual Basic. Обратите внимание, что строка с вызовом NumericValue.IncrementValue метода не назначает значение методу. Вместо этого он назначает значение возвращаемого значения ссылки, возвращаемого методом.

Module Example
   Public Sub Main()
      Dim n As New NumericValue(15)
      n.IncrementValue() += 12
      Console.WriteLine(n.GetValue) 
   End Sub
End Module
' Output:   28

Использование вспомогательного метода

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

В следующем примере C# показан этот сценарий. Он определяет класс, написанный Sentence на языке C#, включает FindNext метод, который находит следующее слово в предложении, которое начинается с указанной подстроки. Строка возвращается как значение, возвращаемое по ссылке, а переменная Boolean, переданная в метод по ссылке, показывает, дал ли поиск какие-то результаты. Возвращаемое значение ссылки указывает, что помимо чтения возвращаемого значения вызывающий объект также может изменить его, и это изменение отражается в данных, содержащихся внутри Sentence класса.

using System;

public class Sentence
{
    private string[] words;
    private int currentSearchPointer;

    public Sentence(string sentence)
    {
        words = sentence.Split(' ');
        currentSearchPointer = -1;
    }

    public ref string FindNext(string startWithString, ref bool found)
    {
        for (int count = currentSearchPointer + 1; count < words.Length; count++)
        {
            if (words[count].StartsWith(startWithString))
            {
                currentSearchPointer = count;
                found = true;
                return ref words[currentSearchPointer];
            }
        }
        currentSearchPointer = -1;
        found = false;
        return ref words[0];
    }

    public string GetSentence()
    {
        string stringToReturn = null;
        foreach (var word in words)
            stringToReturn += $"{word} ";

        return stringToReturn.Trim();
    }
}

Непосредственное изменение возвращаемого значения ссылки в данном случае не является надежным, так как вызов метода может не найти совпадение и вернуть первое слово в предложении. В этом случае вызывающий объект непреднамеренно изменит первое слово предложения. Это может быть запрещено вызывающим методом, возвращающим объект null (или Nothing в Visual Basic). Но в этом случае попытка изменить строку, значение Nothing которой вызывается NullReferenceException. Если также может быть запрещено возвращаемым String.Emptyвызывающим объектом, но это требует, чтобы вызывающий определяет строковую переменную, значение которой равно String.Empty. Хотя вызывающий объект может изменить такую строку, сама модификация не служит никакой целью, так как измененная строка не имеет отношения к словам в предложении, хранящейся Sentence в классе.

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

Module Example
   Public Sub Main()
      Dim sentence As New Sentence("A time to see the world is now.")
      Dim found = False
      Dim returns = RefHelper(sentence.FindNext("A", found), "A good", found) 
      Console.WriteLine(sentence.GetSentence()) 
   End Sub
   
   Private Function RefHelper(ByRef stringFound As String, replacement As String, success As Boolean) _ 
                    As (originalString As String, found As Boolean) 
      Dim originalString = stringFound
      If found Then stringFound = replacement
      Return (originalString, found)   
   End Function
End Module
' The example displays the following output:
'      A good time to see the world is now.

См. также