When declared with var, x is referring to something of type ILRetArray'1
; if declared as ILArray<double>
, it's ILArray'1
. Those are sibling subclasses of a common base (ILDenseArray). A's type is ILArray<double>
and its array-indexing operator returns type ILRetArray<ElementType>
.
There are implicit conversion operators going both ways here between those two classes.
It looks like when A[full, 0]
is assigned to a variable whose type is left up to type inference, the compiler makes it the return type of A's array indexing operator: ILRetArray<ElementType>
. But if you declare x's type explicitly as ILArray<double>
, an implicit conversion operator is invoked and you get a different actual object.
Then you pass it to norm
, which expects ILInArray
, and yet another implicit conversion operator is invoked. And there's a bug in that one. It breaks something in the internal state of ILRetArray. Try this line before the call to norm
:
var d = (ILInArray<double>)x;
...and it will have the same effect on x as the call to norm
did. So it's that conversion.
I haven't downloaded the source to ILNumerics to identify the details of the bug. It's possible that this is meant to be a forbidden operation, in which case I'd wish they had better error reporting (UPDATE see @HaymoKutschbach's answer below: This is in fact the case; ILRetArray
is a volatile type by design, intended to be valid only until the first implicit conversion operator is called on it).
It might be fun to submit a bug report to ILNumerics and see what you hear back (UPDATE: There's a guy from ILN in this thread, so never mind).
But in answer to your question: You do need to be a bit cautious when using var; avoid it when there's any possibility of ambiguity. You need to be especially cautious when implicit conversion operators are involved. I had forgotten those things even existed in C#. I'm not fond of them. Of course the bug wasn't caused by their use of an implicit conversion operator; it's just a bug. But the operators vastly and invisibly confused the issue of what was going on in the code. I prefer type conversions to be visible in the source.
Thanks for posting this, it was fun.