How to Resolve Warning "CS0197: Passing 'argument' as ref or out or taking its address may cause a runtime exception" in C#
The Compiler Warning CS0197 is a warning specific to MarshalByRefObject classes. The message reads: "Passing 'field' as ref or out or taking its address may cause a runtime exception because it is a field of a marshal-by-reference class".
This warning occurs when you try to pass a field of a class that inherits from MarshalByRefObject directly to a method using ref or out. Because MarshalByRefObject instances might live in a different application domain (AppDomain) or on a different machine (via Remoting), accessing their fields directly via memory pointers (ref/out) is unsafe and can crash the application if the object is actually a proxy.
This guide explains the mechanics of marshaling and how to safely pass values from these objects.
Understanding MarshalByRefObject
Normally, objects in C# are referenced by their memory address. However, classes inheriting from MarshalByRefObject are designed to be accessed across boundaries (like different AppDomains).
When you interact with such an object from a different boundary, you aren't holding the real object; you are holding a Proxy.
- Fields: A proxy doesn't have the actual fields in local memory. It has to ask the real object for the value.
ref/out: These keywords require the memory address of the variable.
You cannot give the memory address of a field that doesn't physically exist in your current context (it exists inside the Proxy logic or on a remote server). If you try, the runtime might throw an exception.
Scenario: Direct ref Access to Fields
The warning triggers when you pass a field of a MarshalByRefObject class to a method that expects to modify that memory location directly.
Example of error:
using System;
// This class simulates an object that might live in another AppDomain
public class RemoteService : MarshalByRefObject
{
public int StatusId;
}
public class Program
{
static void UpdateStatus(ref int id)
{
id = 100;
}
static void Main()
{
RemoteService service = new RemoteService();
// ⛔️ Warning CS0197: Passing 'service.StatusId' as ref or out...
// If 'service' is a remote proxy, we cannot get the address of 'StatusId'.
UpdateStatus(ref service.StatusId);
}
}
Solution 1: Use a Local Temporary Variable
The safest and most common fix is to copy the value into a local variable, pass the local variable by reference, and then copy the result back to the field. Local variables always exist in your current stack memory, so they are safe to use with ref.
Solution:
public class Program
{
static void UpdateStatus(ref int id)
{
id = 100;
}
static void Main()
{
RemoteService service = new RemoteService();
// 1. Copy to local variable
int tempId = service.StatusId;
// 2. Pass local variable by ref (Safe)
UpdateStatus(ref tempId);
// 3. Copy result back to the field
// ✅ Correct: We assign the value explicitly, which works across boundaries.
service.StatusId = tempId;
Console.WriteLine(service.StatusId); // Output: 100
}
}
Solution 2: Use Properties (Copy Semantics)
While not a direct fix for ref, using Properties instead of public fields is a best practice that naturally prevents this warning. Properties are methods (get/set) in disguise. You physically cannot pass a property as ref in C#, so the compiler forces you to use the temporary variable pattern (Solution 1) anyway, avoiding the trap entirely.
Refactoring the Class:
public class RemoteService : MarshalByRefObject
{
// Use a Property instead of a Field
public int StatusId { get; set; }
}
public class Program
{
static void UpdateStatus(ref int id) { id = 100; }
static void Main()
{
RemoteService service = new RemoteService();
// UpdateStatus(ref service.StatusId); // Compiler Error (not warning): Cannot pass property as ref.
// This forces you to write correct code:
int temp = service.StatusId;
UpdateStatus(ref temp);
service.StatusId = temp;
}
}
Conclusion
CS0197 warns you that your code assumes the object is local, when it might be remote.
- Check the Class: Does it inherit from
MarshalByRefObject(e.g.,Form,Component, or typical Remoting classes)? - Avoid Field Refs: Do not pass fields of these objects using
reforout. - Use Intermediaries: Copy the value to a local variable, modify the local variable, and assign it back to the field.