How IConfiguration.Bind() Works In .NET Core without 'out' or 'ref' in it's Arguments?

In .NET Core we use IConfiguration to bind configuration to an instance.

var settings = new AppSettings();
Configuration.GetSection("AppSettings").Bind(settings);

To create a similar function like Bind() in my personal project (for a different requirement), I've created a method like this

public void BindOption(ref object instance)
{
  ...
}

And use it like this

var settings = new AppSettings();
MyCustomStaticClass.BindOption(ref settings);

Now my question is

How the Bind() function works without explicitly mentioning out or ref in it's arguments?


Solution 1:

It sounds like you're misunderstanding ref/out - the only thing they do for you when you're working with a reference type (class) passed into a method, is allow the method to assign a new instance of an object to the argument variable, and the calling code sees the change. They are absolutely not needed to change some data content of the passed variable.

I personally think a lot of the confusion surrounding this comes from the phrase "passed by reference" having a word in it that starts with ref, coincidentally being the 3 letters in ref

When you make a reference type instance:

Person john = new Person(){ Name = "John", Age = 27 };

You can pass it to a method:

void ChangeName(Person p){
  p.Name = "Fred";
}

You don't need to specify ref to make this name change and have it stick

ChangeName(john);
Console.Print(john.Name); //Fred

Internally in C#, imagine that you make John and C# allocates some memory, puts the name in it and gives you your variable reference:

john --> { Name: "John", Age: 27 }

You call the method and C# temporarily makes another reference called p (because the method takes a Person p)

john --> { Name: "John", Age: 27 } <-- p

New reference, same object. You change the name via p.Name, original object is affected

john --> { Name: "Fred", Age: 27 } <-- p

If we use ref C# doesn't make a new reference, imagine it just temporarily renames our existing one then names it back when the method is done

void ChangeName(ref Person p){
  p.Name = "Fred";
}


john --> { Name: "John", Age: 27 }      //start with
p --> { Name: "John", Age: 27 }          //when start calling the method 
p --> { Name: "Fred", Age: 27 }          //method changes the person name
john --> { Name: "Fred", Age: 27 }      //method exits, name is changed

We never needed ref here


Different scenario. Person is immutable. The only way to change the name is to swap it for a whole new object

void ChangeName(Person p){
  p = new Person { Name = "Fred", Age: 0 };
}

Now, this needs ref. Look what happens when we don't have ref:

john --> { Name: "John", Age: 27 }
john --> { Name: "John", Age: 27 } <-- p
john --> { Name: "John", Age: 27 }     p --> { Name: "Fred", Age: 0 }
john --> { Name: "John", Age: 27 }

Calling the method makes a new reference to the old object, then saying p = new... reattaches that new reference to some new object, which is promptly destroyed at the end of the method leaving nothing changed

With ref:

john --> { Name: "John", Age: 27 }
p --> { Name: "John", Age: 27 } 
p --> { Name: "Fred", Age 0 }
john --> { Name: "Fred", Age 0 }

Temporarily renaming that reference meant when we made a new object and assigned it, the original calling code experiences the new too


You need ref only if you will set a passed-in thing to a new and want the caller to see the new. Most of the time we don't need it

Footnote: out is like ref except the compiler will check that the method does certainly assign a value. You're required to use "out" or "ref" when passing the variable into the method, because it brings to your attention "this method might overwrite whatever you pass in" (for ref) or "this method will definitely overwrite whatever you pass in" (with out)

Modern .net also has the little-used in modifier, which makes the compiler check that you don't assign a new anything to a passed-in variable (running the risk of the non-ref scenario where Fred is lost at the end of the method)