Compartir a través de


Compatibilidad con valores devueltos de referencia (Visual Basic)

El lenguaje C# admite valores devueltos de referencia. Una manera de comprender los valores de retorno por referencia es que son lo contrario a los argumentos que se pasan por referencia a un método. Cuando se modifica un argumento pasado por referencia, los cambios se reflejan en el valor de la variable del llamador. Cuando un método proporciona un valor devuelto de referencia a un llamador, las modificaciones realizadas en el valor devuelto de referencia por el autor de la llamada se reflejan en los datos del método llamado.

Visual Basic no permite crear métodos con valores devueltos de referencia, pero permite consumir valores devueltos de referencia. En otras palabras, puede llamar a un método con un valor devuelto de referencia y modificar ese valor devuelto y los cambios en el valor devuelto de referencia se reflejan en los datos del método llamado.

Modificación directa del valor devuelto de referencia

En los métodos que siempre se ejecutan correctamente y no tienen parámetros ByRef, puede modificar el valor devuelto de referencia directamente. Para ello, asigne el nuevo valor a las expresiones que devuelven el valor devuelto de referencia.

En el siguiente ejemplo de C# se define un NumericValue.IncrementValue método que incrementa un valor interno y lo devuelve como un valor devuelto de referencia.

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

A continuación, el autor de la llamada modifica el valor devuelto de referencia en el siguiente ejemplo de Visual Basic. Tenga en cuenta que la línea con la NumericValue.IncrementValue llamada al método no asigna un valor al método . En su lugar, asigna un valor al valor devuelto de referencia devuelto por el 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

Uso de un método auxiliar

En otros casos, modificar el valor devuelto de referencia de una llamada de método directamente no siempre puede ser deseable. Por ejemplo, un método de búsqueda que devuelve una cadena puede no encontrar siempre una coincidencia. En ese caso, desea modificar el valor devuelto de referencia solo si la búsqueda se realiza correctamente.

En el ejemplo de C# siguiente se muestra este escenario. Define una Sentence clase escrita en C# incluye un FindNext método que encuentra la siguiente palabra en una oración que comienza con una subcadena especificada. La cadena se devuelve como un valor devuelto de referencia y una Boolean variable pasada por referencia al método indica si la búsqueda se realizó correctamente. El valor devuelto de referencia indica que además de leer el valor devuelto, el autor de la llamada también puede modificarlo y esa modificación se refleja en los datos contenidos internamente en la Sentence clase .

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 modificación directa del valor devuelto de referencia en este caso no es confiable, ya que la llamada al método puede no encontrar una coincidencia y devolver la primera palabra de la oración. En ese caso, el autor de la llamada modificará accidentalmente la primera palabra de la frase. Esto podría evitarse si quien realiza la llamada devuelve un null (o Nothing en Visual Basic). Pero en ese caso, intentar modificar una cadena cuyo valor es Nothing lanza una NullReferenceException. Otra forma de evitarlo es si el llamador devuelve String.Empty, pero esto requiere que el llamador defina una variable de cadena cuyo valor sea String.Empty. Aunque el autor de la llamada puede modificar esa cadena, la propia modificación no tiene ningún propósito, ya que la cadena modificada no tiene ninguna relación con las palabras de la oración almacenada por la Sentence clase .

La mejor manera de controlar este escenario es pasar por referencia el valor devuelto de referencia a un método auxiliar. A continuación, el método auxiliar contiene la lógica para determinar si la llamada al método se realizó correctamente y, si lo hizo, para modificar el valor devuelto de referencia. En el ejemplo siguiente se proporciona una posible implementación.

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.

Consulte también