Suporte para valores de retorno de referência (Visual Basic)
A linguagem C# suporta valores de retorno de referência. Uma maneira de entender os valores de retorno de referência é que eles são o oposto dos argumentos que são passados por referência a um método. Quando um argumento passado por referência é modificado, as alterações são refletidas no valor da variável no chamador. Quando um método fornece um valor de retorno de referência para um chamador, as modificações feitas no valor de retorno de referência pelo chamador são refletidas nos dados do método chamado.
Visual Basic não permite que você crie métodos com valores de retorno de referência, mas permite que você consuma valores de retorno de referência. Em outras palavras, você pode chamar um método com um valor de retorno de referência e modificar esse valor de retorno, e as alterações no valor de retorno de referência são refletidas nos dados do método chamado.
Modificando o valor de retorno ref diretamente
Para métodos que sempre são bem-sucedidos e não ByRef
têm parâmetros, você pode modificar o valor de retorno de referência diretamente. Para fazer isso, atribua o novo valor às expressões que retornam o valor de retorno de referência.
O exemplo C# a seguir define um NumericValue.IncrementValue
método que incrementa um valor interno e o retorna como um valor de retorno de referência.
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;
}
}
O valor de retorno de referência é modificado pelo chamador no seguinte exemplo do Visual Basic. Observe que a linha com a chamada de NumericValue.IncrementValue
método não atribui um valor ao método. Em vez disso, ele atribui um valor ao valor de retorno de referência retornado pelo método.
Module Example
Public Sub Main()
Dim n As New NumericValue(15)
n.IncrementValue() += 12
Console.WriteLine(n.GetValue)
End Sub
End Module
' Output: 28
Usando um método auxiliar
Em outros casos, modificar o valor de retorno de referência de uma chamada de método diretamente nem sempre pode ser desejável. Por exemplo, um método de pesquisa que retorna uma cadeia de caracteres nem sempre pode encontrar uma correspondência. Nesse caso, você deseja modificar o valor de retorno de referência somente se a pesquisa for bem-sucedida.
O exemplo de C# a seguir ilustra esse cenário. Ele define uma Sentence
classe escrita em C# inclui um FindNext
método que localiza a próxima palavra em uma frase que começa com uma substring especificada. A cadeia de caracteres é retornada como um valor de retorno de referência e uma Boolean
variável passada por referência ao método indica se a pesquisa foi bem-sucedida. O valor de retorno de referência indica que, além de ler o valor retornado, o chamador também pode modificá-lo, e essa modificação é refletida nos dados contidos internamente na Sentence
classe.
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();
}
}
Modificar diretamente o valor de retorno de referência neste caso não é confiável, uma vez que a chamada de método pode não encontrar uma correspondência e retornar a primeira palavra na frase. Nesse caso, o chamador modificará inadvertidamente a primeira palavra da frase. Isso pode ser evitado pelo chamador retornando um null
(ou Nothing
no Visual Basic). Mas, nesse caso, tentar modificar uma cadeia de caracteres cujo valor é Nothing
lança um NullReferenceException. Se também pode ser impedido pelo retorno String.Emptydo chamador, mas isso requer que o chamador defina uma variável de cadeia de caracteres cujo valor é String.Empty. Embora o chamador possa modificar essa cadeia de caracteres, a modificação em si não serve para nada, uma vez que a cadeia de caracteres modificada não tem relação com as palavras na frase armazenada pela Sentence
classe.
A melhor maneira de lidar com esse cenário é passar o valor de retorno de referência por referência a um método auxiliar. O método auxiliar contém a lógica para determinar se a chamada de método foi bem-sucedida e, em caso afirmativo, para modificar o valor de retorno de referência. O exemplo a seguir fornece uma possível implementação.
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.