支持引用返回值 (Visual Basic)

C# 语言支持引用返回值。 了解引用返回值的一种方式是,它们与通过引用传递给方法的参数相反。 修改通过引用传递的参数时,更改将反映在调用方的变量值中。 当方法向调用方提供引用返回值时,调用方对引用返回值所做的修改将反映在被调用方法的数据中。

Visual Basic 不允许使用引用返回值创建方法,但允许使用引用返回值。 换句话说,可以使用引用返回值调用方法并修改该返回值,对引用返回值的更改将反映在被调用方法的数据中。

直接修改 ref 返回值

对于总是成功且没有 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# 示例代码演示了此方案。 用 C# 编写的以下 Sentence 类包括 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(或 Visual Basic 中的 Nothing)来阻止。 但在这种情况下,尝试修改其值为 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.

请参阅