The more I see ref used in production code, the more misuse I encounter and the more pain it causes me. I have come to hate this keyword, because from a framework-building s
Hypothetically, I'd guess that you might use a lot of ref/out arguments if you intended to mimic the architecture of older procedural software, for example old game engines and so on. I've scanned the source code of one, I think it was Duke Nukem 3D, and it's procedural with lots of subroutines modifying variables in place, and almost no functions. Obviously, you'd be unlikely to program like this for a real production application unless you had some specific aim in mind.
Any time you want to change the value of a value type - this happens a lot in cases where you want to efficiently update a pair of related values (i.e. rather than returning a struct containing two ints, you pass (ref int x, ref int y))
It's useful when you need efficient in-place algorithms on bignums.
I'm using ref quite often. Just think about functions with multiple return values. It doesn't make sense to create a return object (helper object) or even using hashtables for this purpose.
Example:
getTreeNodeValues(ref selectedValue, ref selectedText);
Edit:
It's better to use out here - as commented.
getTreeNodeValues(out selectedValue, out selectedText);
I'm using it for processing objects:
MyCar car = new MyCar { Name="TestCar"; Wieght=1000; }
UpdateWeight(ref car, 2000);
Another useful example in addition to swap<> is this:
Prompter.getString("Name ? ", ref firstName);
Prompter.getString("Lastname ? ", ref lastName);
Prompter.getString("Birthday ? ", ref firstName);
Prompter.getInt("Id ? ", ref id);
Prompter.getChar("Id type: <n = national id, p = passport, d = driver licence, m = medicare> \n? ", ref c);
public static class Prompter
{
public static void getKey(string msg, ref string key)
{
Console.Write(msg);
ConsoleKeyInfo cki = Console.ReadKey();
string k = cki.Key.ToString();
if (k.Length == 1)
key = k;
}
public static void getChar(string msg, ref char key)
{
Console.Write(msg);
key = Console.ReadKey().KeyChar;
Console.WriteLine();
}
public static void getString(string msg, ref string s)
{
Console.Write(msg);
string input = Console.ReadLine();
if (input.Length != 0)
s = input;
}
public static void getInt(string msg, ref int i)
{
int result;
string s;
Console.Write(msg);
s = Console.ReadLine();
int.TryParse(s, out result);
if (result != 0)
i = result;
}
// not implemented yet
public static string getDate(string msg)
{
// I should use DateTime.ParseExact(dateString, format, provider);
throw new NotImplementedException();
}
}
Use out here it's not an option
Maybe when you have a struct (which is a value type):
struct Foo
{
int i;
public void Test()
{
i++;
}
}
static void update(ref Foo foo)
{
foo.Test();
}
and
Foo b = new Foo();
update(ref b);
Here you would to use two-parameters with out
like:
static void update(Foo foo, out Foo outFoo) //Yes I know you could return one foo instead of a out but look below
{
foo.Test();
outFoo = foo;
}
imaging the method having more than one Foo
then you would get twice the parameters with out
versus ref
. An alternative is to return a N-tuple. I don't have a real-world example on when to use this stuff.
Add on: Different .TryParse
methods could also have avoided out
if they returned Nullable<T>
instead which essentially is a tuple of boolean * T
.