Compatibilidad con los valores devueltos de referencia (Visual Basic)Support for reference return values (Visual Basic)

A partir C# de 7,0, C# el lenguaje admite valores devueltos de referencia.Starting with C# 7.0, the C# language supports reference return values. Una manera de comprender los valores devueltos de referencia es que son lo contrario de los argumentos que se pasan por referencia a un método.One way to understand reference return values is that they are the opposite of arguments that are passed by reference to a method. Cuando se modifica un argumento pasado por referencia, los cambios se reflejan en el valor de la variable en el autor de la llamada.When an argument passed by reference is modified, the changes are reflected in value of the variable on the caller. 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.When an method provides a reference return value to a caller, modifications made to the reference return value by the caller are reflected in the called method's data.

Visual Basic no permite crear métodos con valores devueltos de referencia, pero permite usar valores devueltos de referencia.Visual Basic does not allow you to author methods with reference return values, but it does allow you to consume reference return values. En otras palabras, puede llamar a un método con un valor devuelto de referencia y modificar el valor devuelto, y los cambios en el valor devuelto de referencia se reflejan en los datos del método llamado.In other words, you can call a method with a reference return value and modify that return value, and changes to the reference return value are reflected in the called method's data.

Modificar el valor devuelto de la referencia directamenteModifying the ref return value directly

En el caso de los métodos que siempre se ejecutan correctamente y que no tienen parámetros ByRef, puede modificar el valor devuelto de referencia directamente.For methods that always succeed and have no ByRef parameters, you can modify the reference return value directly. Para ello, se asigna el nuevo valor a las expresiones que devuelven el valor devuelto de referencia.You do this by assigning the new value to the expressions that returns the reference return value.

En el C# ejemplo siguiente se define un método NumericValue.IncrementValue que incrementa un valor interno y lo devuelve como un valor devuelto de referencia.The following C# example defines a NumericValue.IncrementValue method that increments an internal value and returns it as a reference return value.

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

Después, el autor de la llamada modifica el valor devuelto de referencia en el siguiente ejemplo de Visual Basic.The reference return value is then modified by the caller in the following Visual Basic example. Tenga en cuenta que la línea con la llamada al método NumericValue.IncrementValue no asigna un valor al método.Note that the line with the NumericValue.IncrementValue method call does not assign a value to the method. En su lugar, asigna un valor al valor devuelto de referencia que devuelve el método.Instead, it assigns a value to the reference return value returned by the method.

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

Usar un método auxiliarUsing a helper method

En otros casos, puede que no siempre sea deseable modificar el valor devuelto de referencia de una llamada al método directamente.In other cases, modifying the reference return value of a method call directly may not always be desirable. Por ejemplo, un método de búsqueda que devuelve una cadena puede no encontrar siempre una coincidencia.For example, a search method that returns a string may not always find a match. En ese caso, desea modificar el valor devuelto de referencia solo si la búsqueda se realiza correctamente.In that case, you want to modify the reference return value only if the search is successful.

En el C# ejemplo siguiente se muestra este escenario.The following C# example illustrates this scenario. Define una clase Sentence escrita en C# incluye un método FindNext que busca la palabra siguiente en una oración que comienza con una subcadena especificada.It defines a Sentence class written in C# includes a FindNext method that finds the next word in a sentence that begins with a specified substring. La cadena se devuelve como un valor devuelto de referencia, y una variable Boolean que se ha pasado mediante referencia al método indica si la búsqueda se ha realizado correctamente.The string is returned as a reference return value, and a Boolean variable passed by reference to the method indicates whether the search was successful. El valor devuelto de referencia indica que el llamador no solo puede leer el valor devuelto; también puede modificarla, y esa modificación se refleja en los datos incluidos internamente en la clase Sentence.The reference return value indicates that the caller can not only read the returned value; he or she can also modify it, and that modification is reflected in the data contained internally in the Sentence class.

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 es posible que la llamada al método no encuentre una coincidencia y devuelva la primera palabra de la oración.Directly modifying the reference return value in this case is not reliable, since the method call may fail to find a match and return the first word in the sentence. En ese caso, el autor de la llamada modifica accidentalmente la primera palabra de la frase.In that case, the caller will inadvertently modify the first word of the sentence. El autor de la llamada puede evitar que devuelva un null (o Nothing en Visual Basic).This could be prevented by the caller returning a null (or Nothing in Visual Basic). Pero en ese caso, si se intenta modificar una cadena cuyo valor es Nothing se produce una NullReferenceException.But in that case, attempting to modify a string whose value is Nothing throws a NullReferenceException. Si el autor de la llamada también puede evitar que devuelva String.Empty, pero esto requiere que el llamador defina una variable de cadena cuyo valor sea String.Empty.If could also be prevented by the caller returning String.Empty, but this requires that the caller define a string variable whose value is String.Empty. Aunque el autor de la llamada puede modificar esa cadena, la propia modificación no sirve para ningún propósito, ya que la cadena modificada no tiene ninguna relación con las palabras de la frase almacenada por la clase Sentence.While the caller can modify that string, the modification itself serves no purpose, since the modified string has no relationship to the words in the sentence stored by the Sentence class.

La mejor manera de controlar este escenario es pasar el valor devuelto de referencia por referencia a un método auxiliar.The best way to handle this scenario is to pass the reference return value by reference to a helper method. 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.The helper method then contains the logic to determine whether the method call succeeded and, if it did, to modify the reference return value. En el ejemplo siguiente se proporciona una posible implementación.The following example provides a possible implementation.

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.

Vea tambiénSee also