참조 반환 값 지원(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# 예제에서는 이 시나리오를 보여 줍니다. 이 시나리오는 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이 throw됩니다. 호출자가 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.

참고 항목