Supporto per i valori restituiti di riferimento (Visual Basic)

Il linguaggio C# supporta i valori restituiti di riferimento. Un modo per comprendere i valori restituiti di riferimento è che sono l'opposto degli argomenti passati in base al riferimento a un metodo. Quando viene modificato un argomento passato in base al riferimento, le modifiche si riflettono nel valore della variabile sul chiamante. Quando un metodo fornisce un valore restituito di riferimento a un chiamante, le modifiche apportate al valore restituito di riferimento dal chiamante si riflettono nei dati del metodo chiamato.

Visual Basic non consente di creare metodi con valori restituiti di riferimento, ma consente di utilizzare tali valori. In altre parole, è possibile chiamare un metodo con un valore restituito di riferimento e modificare tale valore restituito e le modifiche apportate al valore restituito di riferimento si riflettono nei dati del metodo chiamato.

Modifica diretta del valore restituito di riferimento

Per i metodi che hanno sempre esito positivo e non hanno parametri ByRef, è possibile modificare direttamente il valore restituito di riferimento. A tale scopo, assegnare il nuovo valore alle espressioni che restituiscono il valore restituito di riferimento.

L'esempio C# seguente definisce un metodo NumericValue.IncrementValue che incrementa un valore interno e lo restituisce come valore restituito di riferimento.

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

Il valore restituito di riferimento viene quindi modificato dal chiamante nell'esempio di Visual Basic seguente. Si noti che la riga con la chiamata al metodo NumericValue.IncrementValue non assegna un valore al metodo. Assegna invece un valore al valore restituito di riferimento restituito dal metodo.

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

Utilizzo di un metodo helper

In altri casi, la modifica diretta del valore restituito di riferimento di una chiamata al metodo potrebbe non essere opportuna. Ad esempio, un metodo di ricerca che restituisce una stringa potrebbe non sempre trovare una corrispondenza. In tal caso, si vorrà modificare il valore restituito di riferimento solo se la ricerca ha esito positivo.

L'esempio C# seguente illustra questo scenario. Definisce una classe Sentence scritta in C# che include un metodo FindNext che trova la parola successiva in una frase che inizia con una sottostringa specificata. La stringa viene restituita come valore di riferimento restituito. Una variabile Boolean passata dal riferimento al metodo indica se la ricerca ha avuto esito positivo. Il valore restituito di riferimento indica che oltre a leggere il valore restituito, il chiamante può anche modificarlo e tale modifica si riflette nei dati contenuti internamente nella classe 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();
    }
}

La modifica diretta del valore restituito di riferimento in questo caso non è affidabile, poiché la chiamata al metodo potrebbe non riuscire a trovare una corrispondenza e restituire la prima parola nella frase. In tal caso, il chiamante modificherà inavvertitamente la prima parola della frase. Questo comportamento potrebbe essere impedito dal chiamante che restituisce null (o Nothing in Visual Basic). Ma in questo caso, il tentativo di modificare una stringa il cui valore è Nothing genera un'eccezione NullReferenceException. Potrebbe anche essere impedito dal chiamante che restituisce String.Empty, ma è necessario che il chiamante definisca una variabile stringa il cui valore è String.Empty. Anche se il chiamante può modificare tale stringa, la modifica stessa non ha alcun scopo, poiché la stringa modificata non ha alcuna relazione con le parole nella frase archiviata dalla classe Sentence.

Il modo migliore per gestire questo scenario consiste nel passare il valore restituito di riferimento in base al riferimento a un metodo helper. Il metodo helper contiene quindi la logica per determinare se la chiamata al metodo ha avuto esito positivo e, in caso affermativo, per modificare il valore restituito di riferimento. Nell'esempio seguente viene fornita una possibile implementazione.

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.

Vedi anche