0

If i have a concurrent dictionary, and i try a TryGetValue, and i test if that fails i do stuff, but if it doesn't fail, and the out value retrieved from the TryGetValuefunction is equal to what is was before i tried the TryGetValue, i do something else.

My Question is, (assuming nothing in my ConcurrentDicationary will ever be set to default(DateTime)), will my second if statement ever actually execute? or is it impossible given the current situation?

var m_unitsWaitingForReadResponse = new ConcurrentDictionary<string, DateTime>();
DateTime outVal = default(DateTime);
if (!m_unitsWaitingForReadResponse.TryGetValue("teststring", out outVal))
{
    //Do Stuff
}
if (outVal == default(DateTime))
{
    //Do Stuff 2
}
abatishchev
  • 98,240
  • 88
  • 296
  • 433
jordan
  • 3,436
  • 11
  • 44
  • 75
  • 2
    why not just use an `else` instead of `if (outVal == default(DateTime))`? – Servy Nov 27 '12 at 19:08
  • 1
    The MSDN documentation states that TryGetValue will return `default(TValue)` if the key doesn't exist in the dictionary. So yes, it should execute. You can test the `return` value of `TryGetValue` instead by simply using an `else` clause on the first `if`. – Robert Harvey Nov 27 '12 at 19:09
  • @RobertHarvey thanks, that helps to know that it sets to default(T). if my first if statement is false it will execute, and it leads that the 2nd if statement is true, and will also execute, leading to duplicate code. you should post your statement as a answer ill mark it correct. – jordan Nov 27 '12 at 20:06

3 Answers3

2

The second if block will always execute if a value for the provided key isn't in the ConcurrentDictionary.

Read the Parameters section for the Value at this URL

ConcurrentDictionary.TryGetValue Method

taylorjonl
  • 869
  • 9
  • 15
  • note that it wouldn't be a good idea to rely on this in practice, if nothing else than because you'll confuse other developers who will have the same question the OP has here. – Servy Nov 27 '12 at 19:10
  • +1, but it might be less ambiguous to say "...if the key isn't in the ConcurrentDictionary" – phoog Nov 27 '12 at 19:12
  • @servy, agreed, I would nuke the second if and just use the bool value returned from TryGetValue. – taylorjonl Nov 27 '12 at 19:12
  • 1
    @jordan.peoples Which part of your question do you think taylorjonl overlooked? – phoog Nov 28 '12 at 08:07
1

TryGetValue will always return false, because you haven't put anything into the dictionary. After it returns false, the first if block will not run, but the second if block will run, both if blocks will run, because outVal will have the value of default(DateTime).

If, however, the dictionary has some data in it, it's possible for default(DateTime) to be the value associated with the key you pass to TryGetValue. In that case, the first if block won't run, but the second if block will run.

EDIT:

The original version of the first paragraph above is incorrect. Notice the negation (!) in your if statement:

if (!m_unitsWaitingForReadResponse.TryGetValue("teststring", out outVal))

That expression evaluates to true when TryGetValue returns false. Therefore, you have the following possibilities, though by your assumption, possibility 3 does not apply in your case:

  1. The key is not present in the dictionary
  2. The value associated with the key in the dictionary is not equal to default(DateTime)
  3. The value associated with the key in the dictionary is equal to default(DateTime)

In the first case, TryGetValue returns false; Do Stuff executes; outVal is equal to default(DateTime); and Do Stuff 2 executes.

In the second case, TryGetValue returns true; Do Stuff does not execute; outVal is not equal to default(DateTime); and Do Stuff 2 does not execute.

In the third (impossible) case, TryGetValue returns true; Do Stuff does not execute; outVal is equal to default(DateTime); and Do Stuff 2 executes.

phoog
  • 42,068
  • 6
  • 79
  • 117
  • read the op more carefully, i state assuming all values in the dictionary are NOT default(datetime) – jordan Nov 27 '12 at 20:06
  • @jordan.peoples You're right, I missed that assumption. Reading more carefully, I also noticed the `!` in your original if statement. This means that either both if blocks will execute or neither will. In other words, the `else` approach in the accepted answer changes the meaning of your original code. Perhaps your original code was incorrect, but if it was correct, then the accepted answer is incorrect. – phoog Nov 28 '12 at 23:28
  • No, it is irrevocably correct. point out the usless 2nd block, refactor the useless redundant second block to an else statement, and voila, learned everything. your answer is nice, but his was correct first. he posted in the comment section under my op, the correct asnwer, so i told him to make a post about it and id select his. – jordan Nov 28 '12 at 23:53
  • @jordan.peoples But the accepted answer is correct only because your original code was buggy, which nobody actually mentioned before you did in your comment. – phoog Nov 29 '12 at 01:19
  • that's what the sites for. bring buggy code -> ask question about said code -> receive help on how to change buggy code etc.... – jordan Nov 29 '12 at 05:23
  • 1
    @jordan.peoples of course. But there are two approaches to answering questions here: 1) answer the question as posed or 2) read between the lines and solve the questioner's real problem. Type-2 answers are more helpful to the OP, but they can be confusing to other people who come on the question later. – phoog Nov 29 '12 at 05:41
1

The MSDN documentation states that TryGetValue will return default(TValue) if the key doesn't exist in the dictionary. So yes, it should execute.

You can test the return value of TryGetValue instead by simply using an else clause on the first if, like this:

m_unitsWaitingForReadResponse= new ConcurrentDictionary<string, DateTime>();

DateTime outVal = default(DateTime);

if (!(m_unitsWaitingForReadResponse.TryGetValue("teststring", out outVal)))
{
    //Do Stuff
}
else
{
    //Do Stuff 2
}

I assume that your ConcurrentDictionary object will contain data at some point, using code not seen here.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
  • Except that in the original code, when the key is not in the dictionary, both branches execute, and if the key has a non-default value associated, neither branch executes. I suspect that the original code is incorrect, but if that code is correct, then this code is not. – phoog Nov 28 '12 at 23:25