C# Coding Challenge: What will this code do?
time to read 2 min | 218 words
What is the output of this code?
IDictionary<object,string> instanceToKey = new Dictionary<object, string>(); IDictionary<string, int> keyToCost = new Dictionary<string, int>(); var inst1 = new object(); var inst2 = new object(); instanceToKey[inst1] = "one"; keyToCost["one"] = 1; instanceToKey[inst2] = "two"; keyToCost["two"] = 2; string value = null; foreach (var key in (from inst in new[]{inst1, inst2, new object()} where instanceToKey.TryGetValue(inst, out value) select value)) { int cost; if(keyToCost.TryGetValue(key, out cost)) Console.WriteLine("Key: {0}, Cost: {1}", key, cost); }
Comments
Well it's bloody convoluded, but I couldn't see anything wrong with it. The 3rd instance will be ignored because of the TryGetValue.
Key: One, Cost: 1
Key: Two, Cost: 2
I thought you might have a gotcha in there so I also tried it in .Net 3.5 and 4.0 but got the same result... Is something missing?
Am I missing something? it should be the trivial "one"/1 and "two"/2 pairs
haven't touched .net for a while, but inst1 and inst2 are both new object() - will they have identical hash codes for the dictionary?
if so, the result will be:
Key: two, Cost: 2
Key: two, Cost: 2
Key: two, Cost: 2
+1 to Steve's comment. TryGetValue returns false for the 3rd object and it's never selected.
I was going to agree with dan, but if you run the code it is just
Key: One, Cost: 1
Key: Two, Cost: 2
inst1.Equals(inst2) = false. .GetHashCode() will reveal different hashes too. I guess that makes the difference to the Dictionary type.
I'm agree with Steve too. It's a strange way to process, but you just got :
Key: One, Cost: 1
Key: Two, Cost: 2
The third instance is just ignored...
This is actually what I call a reverse gotcha.
It works as you expect it to, but it doesn't look like it will work.
Sweet! Code that relies on delayed execution, string interning and the semantics of mutating captured variables. That's much better than last time's prefix decrement operator!
Next time, can we have some lock-free multi-threaded code along with the question "what will this code print on an Itanium system?"
Please! ;-) (you might need to specify the chipset though, but then at least participants can't just run the code to solve the quiz!)
Why doesn't it look like it will work?
Looking at the code, it seemed just fine to me.
GetHashCode for classes by default return a unique token by instannce
I'd rewrite this in something like:
foreach (var keyCost in
{
}
public static IEnumerable <tresult ApplyMap <tresult,> (
<tsource source,
<tsource,> keySelector,
<tkey,> map,
<tsource,> resultSelector
)
{
}
TryGetValue() newer fit well in LINQ :-(
I forgot second overload:
public static IEnumerable <tresult ApplyMap <tresult,> (
<tsource source,
<tsource,> map,
<tsource,> resultSelector
)
{
}
"This is actually what I call a reverse gotcha.
It works as you expect it to, but it doesn't look like it will work. "
rofl... Intentionally making something more obscure than it needs to be? That whole debate over Raven DB licensing must have put you in that sort of mood. ;)
To everyone who thinks the is working correctly: change the order in the array so that the 3rd instance is in the middle:
new[]{inst1, new object(), inst2}
Then try to explain out why changing the position of an element that seems to be ignored changes the output of the program.
Daniel: I don't see why it would. And it doesn't.
Thats funny... have what is called "reverse reverse gotchas" all over the place
Code that looks like it shouldn't work and doesn't work
(oh I love the double negative)
I haven't checked but I am pretty sure that I can also produce just the simple "gotcha"
Code that looks like it should work but doesn't work
well the loop input
from inst in new[]{inst1, inst2, new object()} where instanceToKey.TryGetValue(inst, out value) select value
is equivalent to:
new[] {inst1, inst2, new object()}.Where(inst => instanceToKey.TryGetValue(inst, out value)).Select(
I assumed this was equivalent to
new[] {inst1, inst2, new object()}.Where(inst => instanceToKey.TryGetValue(inst, out value)).ToArray().Select(
But its not. So I was all sorts of wrong.
"It works as you expect it to, but it doesn't look like it will work." -> which is why it's important to write the tests first. If it passes, you don't need to code anything else.
Comment preview