次の方法で共有


参照戻り値のサポート (Visual Basic)

C# 言語では、 参照戻り値がサポートされています。 参照戻り値を理解する 1 つの方法は、メソッドへの参照によって渡される引数の逆であるということです。 参照によって渡された引数が変更されると、変更は呼び出し元の変数の値に反映されます。 メソッドが呼び出し元に参照戻り値を提供する場合、呼び出し元によって参照戻り値に加えられた変更は、呼び出されたメソッドのデータに反映されます。

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.

こちらも参照ください