Question
In C#, I am creating a method where I want to pass an object so the method can modify it. What is the difference between these two method signatures?
public void MyFunction(ref MyClass someClass)
and
public void MyFunction(out MyClass someClass)
Which one should I use, and why?
Short Answer
By the end of this page, you will understand how ref and out work in C#, how they differ, and when each should be used. You will also see how they affect method calls, variable assignment, and code clarity in real programs.
Concept
In C#, method arguments are normally passed by value. That means the method receives its own copy of the variable.
When you use ref or out, you are telling C# to pass the variable by reference instead. That means the method can work with the caller's original variable, not just a copy.
This matters because there are two different needs:
refmeans the variable already has a value before the method is called, and the method may read or change it.outmeans the variable does not need a value before the call, but the method must assign one before returning.
Key difference
ref: input and possibly outputout: output only
Why this matters
Choosing between them communicates intent:
- Use
refwhen the method needs the current value and may update it. - Use
outwhen the method's job is to produce a value for the caller.
This helps other developers understand your code and lets the compiler enforce the right rules.
Important note about objects
MyClass is a reference type, but that does not mean ref and out are unnecessary.
If you pass an object normally, the method can modify the object's internal state:
public void UpdateName(MyClass person)
{
person.Name = "Alice";
}
But if you want the method to replace the caller's variable with a different object instance, then you need ref or out:
public void ReplaceObject(ref MyClass person)
{
person = new MyClass();
}
So the real question is often:
- Do you want to modify the object's properties? Normal parameter may be enough.
- Do you want to reassign the caller's variable itself? Use
reforout.
Mental Model
Think of a variable as a labeled sticky note.
- With a normal parameter, the method gets a copy of the sticky note.
- With
ref, the method gets access to the original sticky note. It can read what is currently written there and change it. - With
out, the method gets the original sticky note too, but it should treat it like an empty note that must be filled in before leaving.
Another way to think about it:
ref= "Here is a value I already have; you may update it."out= "Please give me a value back through this variable."
Syntax and Examples
Basic syntax
public void UseRef(ref int number)
{
number = number + 1;
}
public void UseOut(out int number)
{
number = 10;
}
The caller must also use the same keyword:
int a = 5;
UseRef(ref a);
int b;
UseOut(out b);
Example with a class
public class MyClass
{
public string Name { get; set; }
}
Using ref
public void ResetPerson(ref MyClass person)
{
person = new MyClass { Name = "New Person" };
}
MyClass p = new MyClass { Name = "Old Person" };
ResetPerson(ref p);
Console.WriteLine(p.Name); // New Person
Here, the caller already has a value in p, and the method replaces it.
Using out
public void CreatePerson(out MyClass person)
{
person = new MyClass { Name = "Created Person" };
}
MyClass p;
CreatePerson(out p);
Console.WriteLine(p.Name); // Created Person
Here, p does not need a value before the call. The method is responsible for assigning it.
Modifying an object without ref or out
public void RenamePerson(MyClass person)
{
person.Name = "Updated Name";
}
MyClass p = new MyClass { Name = "Original" };
RenamePerson(p);
Console.WriteLine(p.Name); // Updated Name
This works because the method received a copy of the reference, and both variables still point to the same object.
But this does not replace the caller's variable:
public void TryReplace(MyClass person)
{
person = new MyClass { Name = "Different" };
}
MyClass p = new MyClass { Name = "Original" };
TryReplace(p);
Console.WriteLine(p.Name); // Original
The reassignment only affects the local parameter variable inside the method.
Step by Step Execution
Consider this example:
public static void BuildMessage(out string message)
{
message = "Hello";
message += " World";
}
string result;
BuildMessage(out result);
Console.WriteLine(result);
Step by step
-
string result;- A variable named
resultis declared. - It does not yet have a value.
- A variable named
-
BuildMessage(out result);- The method receives access to the caller's actual variable.
- Because it is
out, the method must assignmessagebefore returning.
-
Inside the method:
message = "Hello";- The caller's
resultvariable now has the value"Hello".
- The caller's
-
message += " World";- The value becomes
"Hello World".
- The value becomes
-
The method returns.
resultin the caller now contains"Hello World".
-
Console.WriteLine(result);- Output:
Hello World
- Output:
Compare with ref
public static void AddSuffix(ref string text)
{
text += "!";
}
string value = "Hi";
AddSuffix(ref value);
Console.WriteLine(value);
Step by step:
valuestarts as"Hi".- The method receives the original variable by reference.
- The method reads the current value.
- It appends
"!". - After the method returns,
valueis"Hi!".
This shows the main difference:
outstarts with assignment responsibility inside the method.refstarts with an existing value from the caller.
Real World Use Cases
When ref is used
ref is useful when a method needs an existing value and may update it.
Examples:
- Updating a running total
- Swapping two variables
- Modifying a struct efficiently
- Passing configuration or state that may be changed
Example:
public static void Increment(ref int count)
{
count++;
}
When out is used
out is commonly used when a method tries to produce a result in addition to returning success or failure.
Examples:
- Parsing text into another type
- Returning a computed value from a lookup
- Returning multiple results from one method
Example:
if (int.TryParse("123", out int number))
{
Console.WriteLine(number);
}
This is a classic out pattern:
- The method returns
trueorfalse - The parsed value comes back through the
outparameter
For your specific situation
If your method only needs to change properties on the object, you usually do not need either ref or out.
If your method needs to assign a brand new object to the caller's variable:
- use
refif the caller already has a meaningful object/value - use
outif the method is responsible for creating and returning one
Real Codebase Usage
In real codebases, ref and out are used less often than beginners expect.
Common pattern: no ref needed for object mutation
Developers often write methods like this:
public void ApplyDiscount(Order order)
{
order.Total = order.Total * 0.9m;
}
Because Order is a reference type, its properties can be updated without ref.
Common pattern: out for Try-methods
A very common convention in .NET is the Try... pattern:
public bool TryGetUser(string id, out User user)
{
user = repository.Find(id);
return user != null;
}
This is used for:
- parsing
- dictionary lookups
- cache retrieval
- validation with result output
Common pattern: early return with out
public bool TryCreateEmail(string input, out string email)
{
if (string.IsNullOrWhiteSpace(input))
{
email = string.Empty;
return false;
}
email = input.Trim().ToLower();
return true;
}
Notice that every path assigns email. The compiler requires that for out.
Guarded updates with ref
ref is more likely when working with value types or when a variable truly needs to be replaced.
public void NormalizeScore(ref int score)
{
if (score < 0)
{
score = 0;
return;
}
if (score > 100)
{
score = 100;
}
}
API design tip
If a method feels awkward with many out parameters, it is often better to return a custom object instead. That usually improves readability.
Common Mistakes
1. Using ref when plain object mutation is enough
Broken thinking:
public void ChangeName(ref MyClass person)
{
person.Name = "Alice";
}
This works, but ref is unnecessary if you are only changing properties.
Better:
public void ChangeName(MyClass person)
{
person.Name = "Alice";
}
2. Forgetting to initialize a ref variable before calling
Broken code:
int x;
UseRef(ref x); // Error
Why it fails:
refrequires the variable to already be assigned.
Correct:
int x = 0;
UseRef(ref x);
3. Forgetting to assign an out parameter in all code paths
Broken code:
public bool TryGetValue(bool ok, out int result)
{
if (ok)
{
result = 1;
return true;
}
return false; // Error: result was not assigned
}
Correct:
public bool TryGetValue(bool ok, out int result)
{
if (ok)
{
result = 1;
return true;
}
result = 0;
return false;
}
4. Thinking out means "optional"
out does not mean the method may skip assignment. It means the opposite: assignment is required.
5. Forgetting the keyword at the call site
Broken code:
int x = 5;
UseRef(x); // Error
Correct:
int x = 5;
UseRef(ref x);
6. Replacing an object without ref
Broken expectation:
public void Replace(MyClass item)
{
item = new MyClass();
}
This does not replace the caller's variable.
Use ref or out if you need that behavior.
Comparisons
| Feature | ref | out | Normal parameter |
|---|---|---|---|
| Passed by reference | Yes | Yes | No |
| Must be assigned before method call | Yes | No | Yes |
| Must be assigned inside method | No | Yes | No |
| Method can read existing value immediately | Yes | No, not safely before assignment | Yes |
| Good for input and output | Yes | No, mainly output | No |
| Good for returning a produced value | Sometimes | Yes | No |
ref vs out
- Use
refwhen the incoming value matters. - Use
outwhen the method is supposed to create or supply the value.
out vs return value
| Option | Best when |
|---|---|
| Return value | The method produces one main result |
out parameter | The method returns success/failure and also needs to provide a value |
| Custom object | The method needs to return several related values clearly |
For reference types specifically
| Goal | Need ref/out? |
|---|---|
| Change object properties | Usually no |
| Replace the object variable itself | Yes |
| Create a new object for caller | out often fits |
| Update an existing object variable based on its current value | ref often fits |
Cheat Sheet
Quick rules
ref= variable must already have a value before the callout= variable does not need a value before the calloutparameter must be assigned inside the method before it returns- Both
refandoutmust appear in:- the method declaration
- the method call
Syntax
void Update(ref int x)
{
x = x + 1;
}
void Create(out int x)
{
x = 10;
}
Calling
int a = 5;
Update(ref a);
int b;
Create(out b);
Object rule
For classes:
void Change(MyClass obj)
{
obj.Name = "Updated"; // no ref needed
}
But to replace the variable itself:
void Replace(ref MyClass obj)
{
obj = new MyClass();
}
Choose this
- Use normal parameter if only changing object contents
- Use
refif the method needs the current variable value and may replace/update it - Use
outif the method's job is to produce a value for the caller
Common edge case
This does not replace the caller's object:
void Wrong(MyClass obj)
{
obj = new MyClass();
}
Because only the local copy of the reference changes.
FAQ
Do I need ref to modify a class object in C#?
No. If you only want to change the object's properties or fields, you can pass the object normally.
When should I use out instead of ref?
Use out when the method is meant to assign and return a value through the parameter, especially in Try... methods.
Can ref and out both change the caller's variable?
Yes. Both pass the variable by reference, so both can change the caller's variable.
Why must an out parameter be assigned inside the method?
Because out means the method is responsible for producing that value. The compiler enforces this rule.
Is out only for primitive types?
No. It can be used with classes, structs, and other types.
If I want to replace an object with a new instance, should I use ref or out?
Use ref if the caller already has a meaningful value and the method may update or replace it. Use out if the method is supposed to provide the object from scratch.
Why do many C# methods avoid ref and out?
Because they can make APIs harder to read. Often a return value or a small result object is clearer.
Mini Project
Description
Build a small C# console example that demonstrates all three cases: modifying an object's property with a normal parameter, replacing an object with ref, and creating an object with out. This helps you see exactly when ref and out are necessary and when they are not.
Goal
Create a program that shows the difference between normal parameters, ref, and out using a simple Person class.
Requirements
- Create a
Personclass with aNameproperty. - Write one method that changes
Namewithout usingreforout. - Write one method that replaces a
Personobject usingref. - Write one method that creates a new
Personusingout. - Print results before and after each method call to compare behavior.
Keep learning
Related questions
AddTransient vs AddScoped vs AddSingleton in ASP.NET Core Dependency Injection
Learn the differences between AddTransient, AddScoped, and AddSingleton in ASP.NET Core DI with examples and practical usage.
Best Way to Repeat a Character in C#: Building Repeated Strings Efficiently
Learn the best way to repeat a character in C#, compare StringBuilder, string concatenation, and simpler built-in options.
C# Access Modifiers and static: public, private, protected, and Defaults
Learn how C# public, private, protected, and default access control visibility, and how static differs from instance members.