Gather round folks, it is time for lesson time.
So we can pass stuff into methods with parameters, and we know that when using primitives and enums, the value is passed, while with objects the reference is passed. This means that any change to a primitive inside a method will not affect that value for what ever called it.
But what if we
want to affect it? What if we want to be able to change values with a method the same way we do with objects?
Lets start with some simple code.
class Program
{
static void Main(string[] args)
{
int x = 14;
x = clamp(x, 0, 10);
Console.WriteLine("Value: " + x);
Console.ReadKey();
}
static int clamp(int value, int max, int min)
{
if (value > max)
return max;
if (value < min)
return min;
return value;
}
}
Ok, so we take a value, and then we make sire it is between two other values. You would be surprised how useful that can be for games, but anyway. Wouldn't it be nice if we didn't have to reassign x after calling the method, if instead the method could just change x? Well we can do that with the 'ref' keyword! For example...
static void clamp(ref int value, int max, int min)
{
if (value > max)
value = max;
if (value < min)
value = min;
}
Now it will pass the reference to an int in, rather than copying its value over to the new method. But wait, the compiler is angry with us... Red lines over in the main! First and for most, we are still trying to assign x a value, even though the method returns void, and we don't need to any more, so we can fix that.
static void Main(string[] args)
{
int x = 14;
clamp(x, 0, 10);
Console.WriteLine("Value: " + x);
Console.ReadKey();
}
But something is still wrong. The problem is that we are trying to pass in an int, not the
reference to an int, although the method now takes a reference, the thing calling it will still try to copy the old value over. To fix this, we add the ref keyword to the calling method.
static void Main(string[] args)
{
int x = 14;
clamp(ref x, 0, 10);
Console.WriteLine("Value: " + x);
Console.ReadKey();
}
There! Run that, and enjoy. Now you may be asking, what about objects? Does this ref keyword work for them too? And if so, how? Well yes it does, and in basically it can be used to swap objects around.
Let's bring back my favourite test class, the 'Person' class.
class Person
{
private string name;
public Person(string name)
{
this.name = name;
}
public string Name
{
get
{
return name;
}
}
}
Now you know that thing from the matrix, where Agent Smith turns people into himself? That was awesome! Let's program that! First add this simple method.
static void smithithy(Person person)
{
person = new Person("Agent Smith");
}
And this to the main
static void Main(string[] args)
{
Person anderson = new Person("Mr. Anderson");
smithify(anderson);
Console.WriteLine("Why hello {0}!", anderson.Name);
Console.ReadKey();
}
Now because objects are always passed around by reference, it should replace Anderson with Smith, right?
Now run that and... DAMMIT! Foiled again! But this time, not because Neo went all chosen one, but because we didn't get our pointers right. See this is what happened...
The main was looking at Anderson, and told the method where to look by copying over the location of Anderson.
However, when it make Smith, it just forgot about Anderson, and didn't bother to do anything with the pointer in the main.
So we want to change what the main is looking at. To do that we need a pointer to a pointer!
So we do this with the 'ref' keyword, once again. Just like before, add it to the parameters.
static void Main(string[] args)
{
Person anderson = new Person("Mr. Anderson");
smithify(ref anderson);
Console.WriteLine("Why hello {0}!", anderson.Name);
Console.ReadKey();
}
static void smithify(ref Person person)
{
person = new Person("Agent Smith");
}
Now when we do anything in the smithify method, we are making the variable in the main do something. Run that aaand...
Continues in part 2