支援參考傳回值(可視基本值)Support for reference return values (Visual Basic)

從 C# 7.0 開始,C# 語言支援參考傳回值Starting with C# 7.0, the C# language supports reference return values. 理解引用傳回值的一種方法是,它們是通過引用傳遞給方法的參數的相反。One way to understand reference return values is that they are the opposite of arguments that are passed by reference to a method. 修改引用傳遞的參數時,更改將反映在調用方上的變數的值中。When an argument passed by reference is modified, the changes are reflected in value of the variable on the caller. 當方法向調用方提供引用傳回值時,調用方對引用傳回值所做的修改將反映在被呼叫者法的資料中。When an method provides a reference return value to a caller, modifications made to the reference return value by the caller are reflected in the called method's data.

Visual Basic 不允許使用引用傳回值編寫方法,但它確實允許您使用引用傳回值。Visual Basic does not allow you to author methods with reference return values, but it does allow you to consume reference return values. 換句話說,可以調用具有引用傳回值的方法並修改該傳回值,對引用傳回值的更改將反映在被調用的方法的資料中。In other words, you can call a method with a reference return value and modify that return value, and changes to the reference return value are reflected in the called method's data.

直接修改 ref 傳回值Modifying the ref return value directly

對於始終成功且沒有ByRef參數的方法,可以直接修改引用傳回值。For methods that always succeed and have no ByRef parameters, you can modify the reference return value directly. 為此,通過將新值分配給返回引用傳回值的運算式。You do this by assigning the new value to the expressions that returns the reference return value.

下面的 C# 示例定義了一NumericValue.IncrementValue個方法,該方法將內部值遞增並返回為引用傳回值。The following C# example defines a NumericValue.IncrementValue method that increments an internal value and returns it as a reference return value.

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 示例中修改引用傳回值。The reference return value is then modified by the caller in the following Visual Basic example. 請注意,使用 方法調用NumericValue.IncrementValue的行不會為 方法分配值。Note that the line with the NumericValue.IncrementValue method call does not assign a value to the method. 相反,它將值分配給方法返回的引用傳回值。Instead, it assigns a value to the reference return value returned by the method.

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

使用説明器方法Using a helper method

在其他情況下,直接修改方法調用的引用傳回值可能並不總是可取的。In other cases, modifying the reference return value of a method call directly may not always be desirable. 例如,返回字串的搜索方法可能並不總是找到匹配項。For example, a search method that returns a string may not always find a match. 在這種情況下,僅當搜索成功時,才要修改引用傳回值。In that case, you want to modify the reference return value only if the search is successful.

以下 C# 示例說明了此方案。The following C# example illustrates this scenario. 它定義用SentenceC# 編寫的類包括一FindNext個方法,該方法在以指定的子字串開頭的句子中查找下一個單詞。It defines a Sentence class written in C# includes a FindNext method that finds the next word in a sentence that begins with a specified substring. 字串會以參考傳回值傳回,而參考所傳遞至方法的 Boolean 變數會指出搜尋是否成功。The string is returned as a reference return value, and a Boolean variable passed by reference to the method indicates whether the search was successful. 引用傳回值指示除了讀取返回的值外,調用方還可以修改它,並且該修改反映在Sentence類內部包含的資料中。The reference return value indicates that in addition to reading the returned value, the caller can also modify it, and that modification is reflected in the data contained internally in the Sentence class.

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();
    }
}

在這種情況下,直接修改引用傳回值不可靠,因為方法調用可能無法找到匹配項並返回句子中的第一個單詞。Directly modifying the reference return value in this case is not reliable, since the method call may fail to find a match and return the first word in the sentence. 在這種情況下,調用方將無意中修改句子的第一個單詞。In that case, the caller will inadvertently modify the first word of the sentence. 調用方返回 (nullNothing視覺基本值) 可以防止這種情況。This could be prevented by the caller returning a null (or Nothing in Visual Basic). 但是在這種情況下,嘗試修改其值為Nothing的字串將引發 。 NullReferenceExceptionBut in that case, attempting to modify a string whose value is Nothing throws a NullReferenceException. 如果調用方也可以阻止 返回String.Empty,但這需要調用方定義其值為String.Empty的字串變數。If could also be prevented by the caller returning String.Empty, but this requires that the caller define a string variable whose value is String.Empty. 雖然調用方可以修改該字串,但修改本身沒有用處,因為修改後的字串與Sentence類存儲的句子中的單詞沒有關系。While the caller can modify that string, the modification itself serves no purpose, since the modified string has no relationship to the words in the sentence stored by the Sentence class.

處理此方案的最佳方法是通過引用説明器方法傳遞引用傳回值。The best way to handle this scenario is to pass the reference return value by reference to a helper method. 然後,説明器方法包含邏輯,以確定方法調用是否成功,如果成功,則修改引用傳回值。The helper method then contains the logic to determine whether the method call succeeded and, if it did, to modify the reference return value. 下面的示例提供了一個可能的實現。The following example provides a possible implementation.

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.

另請參閱See also