支持引用返回值 (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# 示例演示了此方案。 它定义 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(或 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.

另请参阅