6

Take the following code for exhibit A:

string sql;
if (!GetQueries.TryGetValue(type.TypeHandle, out sql))

Documentation for Dictionary says that if the Key isn't found, the reference type will be set to null. OK, that's fine.

If the key is found, how is the variable 'sql' filled? Is the found value for the key cloned? Is a type of object for the item found created and then the contents of the object copied? Is this safe?

Or, to set up a place for the outbound object to reside, should the call be set up as exhibit B:

var sql = string.Empty;
if (!GetQueries.TryGetValue(type.TypeHandle, out sql))

Then the variable 'sql' is initialized and a safe place for the object exists.

(My question comes from my aversion of null pointers in my C programming days.)

Robert Achmann
  • 1,986
  • 3
  • 40
  • 66
  • [`out` C# Reference](http://msdn.microsoft.com/en-us/library/t3c3bfhx.aspx) "Although variables passed as out arguments do not have to be initialized before being passed, the called method is required to assign a value before the method returns." – Habib Sep 25 '14 at 13:49

2 Answers2

9

In my view, it's better not to set it to a value. After all, that value is guaranteed to be replaced by the method call (assuming that doesn't throw an exception) so why bother specifying a value which is pointless? It just misleads the reader into thinking it makes a difference.

An out parameter is special in that the variable you use to provide a value for it doesn't have to be definitely-assigned before the call, but will be definitely-assigned after the call. Any value it has before the call will not be visible to the method.

(Note that ref parameters don't behave that way - they have to be definitely assigned beforehand.)

See my article on C# argument passing for more details on the different parameter modes in C#.

If the key is found, how is the variable 'sql' filled? Is the found value for the key cloned? Is a type of object for the item found created and then the contents of the object copied?

The value of the parameter within the method becomes the value of the variable in the callers code, in the same way as normal assignment. There is no object cloning going on.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    Just also wanted to add that `ref` parameters differ from `out` parameters in that they *must* be initialized before being passed to the function. – Anthony Sep 25 '14 at 13:49
  • @Anthony: Yup, will add that detail. – Jon Skeet Sep 25 '14 at 13:49
  • It's also worth noting that if you initialize the variable to a value and then pass it to TryGetValue, a decent code analysis tool such as Resharper will warn you that the variable is assigned a value that is never used, and advise you to remove the unnecessary initialization. – Mike Hofer Sep 25 '14 at 13:51
  • In addition, if you omit the `TryGetValue` call and read the variable, you will get an uninitialized instance variable compilation error. – Matthew Sep 25 '14 at 13:53
  • Thanks - figured it was better to get the right answer than just assume my own. ;) – Robert Achmann Sep 25 '14 at 14:11
0

If the key is found, how is the variable 'sql' filled?

You can think it like this:

var sql = GetQueries[type.TypeHandle];

Or, to set up a place for the outbound object to reside, should the call be set up as exhibit B:

No actually it doesn't matter. You don't have to initialize sql to a value, since you are passing it as out argument.The function guarantees that it will set the value of it's argument by declaring it as out.

Selman Genç
  • 100,147
  • 13
  • 119
  • 184