C# Pass By Reference (How It Works For Developers)

In C#, passing variables to methods can be done in two main ways: pass by value and pass by reference. Pass by reference is a method that allows you to pass the reference of a variable, rather than a copy of its value, to a method. This means that any changes made to the variable in the called method will reflect in the calling method because both the method definition and the calling method interact with the same memory location.

In this article, we'll talk about the Pass by reference concept and the IronPDF library.

Understanding Ref Keyword

The ref keyword plays a central role in passing by reference. It is used in both the method definition and the method call to indicate that an argument is passed by reference. This keyword ensures that a method can change the value of the argument passed to it.

The ref keyword can be used with both value types and reference types, but its effect is most noticeable with value types because it allows changes to the value type to be reflected outside the method call.

Practical Example: Using Ref Keyword

Consider a scenario where you want to write a method that doubles the value of a number. By using the ref keyword, you can ensure that the original variable's value is modified.

public class Program
{
    public static void Main(string[] args)
    {
        int number = 10;
        Double(ref number);
        Console.WriteLine(number); // Output: 20
    }
    static void Double(ref int number)
    {
        number *= 2;
    }
}
public class Program
{
    public static void Main(string[] args)
    {
        int number = 10;
        Double(ref number);
        Console.WriteLine(number); // Output: 20
    }
    static void Double(ref int number)
    {
        number *= 2;
    }
}
Public Class Program
	Public Shared Sub Main(ByVal args() As String)
		Dim number As Integer = 10
		Double(number)
		Console.WriteLine(number) ' Output: 20
	End Sub
	Private Shared Sub Double(ByRef number As Integer)
		number *= 2
	End Sub
End Class
VB   C#

In the above example, the ref int number in the Double method signifies that the number variable is a reference parameter. When the Double method is called with ref number, it directly modifies the original number variable's value to 20.

Ref Parameters and Method Definitions

Ref parameters must be explicitly stated in both the method definition and the method call. This requirement ensures clarity in the code, making it obvious when a variable is being passed by reference. It's essential to remember that the initial values of ref parameters must be set before they can be passed to a method because the method might access or modify the value.

Example: Swapping Two Numbers

A common use of ref parameters is in a swap function, where two variables' values are swapped:

public class Program
{
    public static void Main()
    {
        int a = 5, b = 10;
        Swap(ref a, ref b);
        Console.WriteLine($"a: {a}, b: {b}"); // Output: a: 10, b: 5
    }
    static void Swap(ref int x, ref int y)
    {
        int temp = x;
        x = y;
        y = temp;
    }
}
public class Program
{
    public static void Main()
    {
        int a = 5, b = 10;
        Swap(ref a, ref b);
        Console.WriteLine($"a: {a}, b: {b}"); // Output: a: 10, b: 5
    }
    static void Swap(ref int x, ref int y)
    {
        int temp = x;
        x = y;
        y = temp;
    }
}
Public Class Program
	Public Shared Sub Main()
		Dim a As Integer = 5, b As Integer = 10
		Swap(a, b)
		Console.WriteLine($"a: {a}, b: {b}") ' Output: a: 10, b: 5
	End Sub
	Private Shared Sub Swap(ByRef x As Integer, ByRef y As Integer)
		Dim temp As Integer = x
		x = y
		y = temp
	End Sub
End Class
VB   C#

In this example, Swap uses ref parameters to directly modify the memory locations of the variables a and b, effectively swapping their values.

Distinguishing Between Value and Reference Types

Understanding the difference between value types and reference types is crucial when dealing with a pass by reference. Value types hold the data directly in their memory location, whereas reference types store a reference to the actual data stored in a different memory location.

Using the ref keyword with reference types allows you to modify the reference itself, for example, pointing it to a new object.

Example: Modifying Reference Type

Consider modifying a Person object's name through a method:

public class Person
{
    public string Name { get; set; }
}
public class Program
{
    public static void Main()
    {
        Person person = new Person { Name = "John" };
        ChangeName(ref person);
        Console.WriteLine(person.Name); // Output: Jane
    }
    static void ChangeName(ref Person p)
    {
        p = new Person { Name = "Jane" };
    }
}
public class Person
{
    public string Name { get; set; }
}
public class Program
{
    public static void Main()
    {
        Person person = new Person { Name = "John" };
        ChangeName(ref person);
        Console.WriteLine(person.Name); // Output: Jane
    }
    static void ChangeName(ref Person p)
    {
        p = new Person { Name = "Jane" };
    }
}
Public Class Person
	Public Property Name() As String
End Class
Public Class Program
	Public Shared Sub Main()
		Dim person As New Person With {.Name = "John"}
		ChangeName(person)
		Console.WriteLine(person.Name) ' Output: Jane
	End Sub
	Private Shared Sub ChangeName(ByRef p As Person)
		p = New Person With {.Name = "Jane"}
	End Sub
End Class
VB   C#

Here, the ChangeName method changes the original person object's reference to a new Person object with a different name.

Out Keyword for Returning Multiple Values

Another keyword closely related to ref is out. The out keyword is used for passing arguments to methods as references. It is particularly useful when you want a method to return multiple values. Unlike ref, variables passed with out do not need to be initialized before being passed to a method.

Example: Returning Multiple Values

public class Program
{
    public static void Main()
    {
        GetValues(out int a, out int b);
        Console.WriteLine($"a: {a}, b: {b}");
    }
    static void GetValues(out int x, out int y)
    {
        x = 5;
        y = 10;
    }
}
public class Program
{
    public static void Main()
    {
        GetValues(out int a, out int b);
        Console.WriteLine($"a: {a}, b: {b}");
    }
    static void GetValues(out int x, out int y)
    {
        x = 5;
        y = 10;
    }
}
Public Class Program
	Public Shared Sub Main()
		Dim a As Integer
		Dim b As Integer
		GetValues(a, b)
		Console.WriteLine($"a: {a}, b: {b}")
	End Sub
	Private Shared Sub GetValues(ByRef x As Integer, ByRef y As Integer)
		x = 5
		y = 10
	End Sub
End Class
VB   C#

In this example, GetValues uses the out keyword to return two integers to the caller. This illustrates how theout keyword enables a method to output multiple values without returning a complex object or using out parameters.

Using Params for Flexible Method Parameters

Another keyword that enhances how you pass arguments to methods is params. The params keyword allows you to specify a method parameter that takes a variable number of arguments. This can be especially useful when the exact number of inputs your method needs to handle is not fixed.

Example: Summation with Params

public class Program
{
    public static void Main()
    {
        int sum = Sum(1, 2, 3, 4, 5); // You can pass any number of arguments
        Console.WriteLine($"Sum: {sum}");
    }
    static int Sum(params int[] numbers)
    {
        return numbers.Sum();
    }
}
public class Program
{
    public static void Main()
    {
        int sum = Sum(1, 2, 3, 4, 5); // You can pass any number of arguments
        Console.WriteLine($"Sum: {sum}");
    }
    static int Sum(params int[] numbers)
    {
        return numbers.Sum();
    }
}
Public Class Program
	Public Shared Sub Main()
		Dim sum As Integer = Sum(1, 2, 3, 4, 5) ' You can pass any number of arguments
		Console.WriteLine($"Sum: {sum}")
	End Sub
	Private Shared Function Sum(ParamArray ByVal numbers() As Integer) As Integer
		Return numbers.Sum()
	End Function
End Class
VB   C#

In this code snippet, the Sum method uses the params keyword to accept an array of integers. This way, the method can handle any number of integer arguments and sum them up, demonstrating the flexibility that params provide for method parameters.

Understanding the Difference Between Ref, Out, and Params

While ref, out, and params keywords improve how methods receive arguments in C#, they serve different purposes:

  • ref is used to pass a variable by its reference, allowing the method to modify the caller's variable.
  • out is similar to ref but is specifically designed for methods that need to return multiple values. Variables passed as out parameters do not need to be initialized beforehand.
  • params offer a way to pass a variable number of arguments to a method, making your methods more flexible in terms of the number of inputs they can handle.

Introduction of the IronPDF Library

IronPDF is a .NET PDF library developed for developers working with C# to create, manipulate, and read PDF files effortlessly. Developers can create PDF files from HTML Strings, HTML files, and URLs. It also offers advance PDF editing features like headers, footers, watermarks, and many more. Its simple integration into C# projects using NuGet simplifies dealing with PDF files.

When you pass parameters by reference using the ref keyword in C#, you're essentially allowing a method to modify the object you're passing. This method of passing reference parameters helps while working with large objects or resources like PDF files, as it ensures you're always interacting with the same object across different method calls, reducing overhead and enhancing performance.

Code Example

Consider the following simple code example that demonstrates using the ref parameter with IronPDF to modify a PDF document within a method:

using IronPdf;
using IronPdf.Editing;
public class PdfEditor
{
    public void AddWatermark(ref PdfDocument document, string watermarkText, int opacity = 90, VerticalAlignment verticalAlignment = IronPdf.Editing.VerticalAlignment.Middle, HorizontalAlignment horizontalAlignment = IronPdf.Editing.HorizontalAlignment.Center)
    {
        document.ApplyWatermark(watermarkText, opacity, verticalAlignment, horizontalAlignment);
    }
}
class Program
{
    static void Main(string[] args)
    {
        License.LicenseKey = "ILicense-Key";
        var pdf = new PdfDocument("Report.pdf");
        var editor = new PdfEditor();
        // Passing the 'pdf' object by reference. Any changes made in 'AddWatermark' affect the original 'pdf' object.
        editor.AddWatermark(ref pdf, "<h2>Confidential</h2>");
        // Save the modified document
        pdf.SaveAs("modified_document.pdf");
    }
}
using IronPdf;
using IronPdf.Editing;
public class PdfEditor
{
    public void AddWatermark(ref PdfDocument document, string watermarkText, int opacity = 90, VerticalAlignment verticalAlignment = IronPdf.Editing.VerticalAlignment.Middle, HorizontalAlignment horizontalAlignment = IronPdf.Editing.HorizontalAlignment.Center)
    {
        document.ApplyWatermark(watermarkText, opacity, verticalAlignment, horizontalAlignment);
    }
}
class Program
{
    static void Main(string[] args)
    {
        License.LicenseKey = "ILicense-Key";
        var pdf = new PdfDocument("Report.pdf");
        var editor = new PdfEditor();
        // Passing the 'pdf' object by reference. Any changes made in 'AddWatermark' affect the original 'pdf' object.
        editor.AddWatermark(ref pdf, "<h2>Confidential</h2>");
        // Save the modified document
        pdf.SaveAs("modified_document.pdf");
    }
}
Imports IronPdf
Imports IronPdf.Editing
Public Class PdfEditor
	Public Sub AddWatermark(ByRef document As PdfDocument, ByVal watermarkText As String, Optional ByVal opacity As Integer = 90, Optional ByVal verticalAlignment As VerticalAlignment = IronPdf.Editing.VerticalAlignment.Middle, Optional ByVal horizontalAlignment As HorizontalAlignment = IronPdf.Editing.HorizontalAlignment.Center)
		document.ApplyWatermark(watermarkText, opacity, verticalAlignment, horizontalAlignment)
	End Sub
End Class
Friend Class Program
	Shared Sub Main(ByVal args() As String)
		License.LicenseKey = "ILicense-Key"
		Dim pdf = New PdfDocument("Report.pdf")
		Dim editor = New PdfEditor()
		' Passing the 'pdf' object by reference. Any changes made in 'AddWatermark' affect the original 'pdf' object.
		editor.AddWatermark(pdf, "<h2>Confidential</h2>")
		' Save the modified document
		pdf.SaveAs("modified_document.pdf")
	End Sub
End Class
VB   C#

C# Pass By Reference (How It Works For Developers): Figure 1

In this example, the AddWatermark method modifies the PdfDocument object directly because it's passed by reference. This means the pdf object in the Main method reflects any changes made by AddWatermark.

Conclusion

In conclusion, understanding how to use pass by reference in C# is crucial for developers looking to manipulate variables directly within methods or return multiple values efficiently. The correct application of ref, out, and params keywords enhances the functionality and flexibility of your code.

If you're working on projects that require advanced PDF functionalities, IronPDF offers a compelling solution with its robust library. They provide a free trial options start from $749.