Pop Quiz!
Alright class. Pop quiz time. Say you have the following code:
namespace What { class The { public static void Heck(uint[] array) { if (typeof(uint) != array.GetValue(0).GetType()) { throw new PleaseExplainThisToMeException(); } } } }
Under what circumstances could you expect the "PleaseExplainThisToMeException" thrown?
Note: You should be able to make the exception get thrown by just
making a regular call to this in C# without any use of things like
unsafe code or the like.
Comments
- Anonymous
July 02, 2005
If the function were called from some other unspecified method which wasn't strict about the type checking, and passed a non-null array with at least 1 element, the first element being non-uint, the exception should be thrown.
You should be able to generate such a method directly in IL (or using LCG in Whidbey), provided the call OpCode doesn't itself enforce type safety.
Just a guess on my part. You see this sort of manual type-checking in dynamic languages frequently, as well as in HP48 System RPL. - Anonymous
July 02, 2005
Nope. You don't need IL. I'll update the post accordingly. - Anonymous
July 02, 2005
You can expect the exception to be thrown when the Martians attack.
Or something like that. - Anonymous
July 03, 2005
int[] array = new int[1];
array[0] = 1; What.The.Heck((uint[])(object)array); - Anonymous
July 03, 2005
See my blog on the subject... http://wesnerm.blogs.com/net_undocumented/2005/07/array_covarianc.html on Array Covariance for Enums.
Arrays of enums are compatible with arrays of underlying integer type. Also, arrays of enums with the same underlying integer type are also compatible.
Since the C# compiler disallows the direct conversion from arrays of enums to arrays of ints, an indirect conversion to the type Array or Object needs to first performed.
uint[] array = (uint[]) (Array) new uintEnum[1];
The CLR treats array of enums and array of integers virtually identically. - Anonymous
July 03, 2005
Interesting task! I've tried all solutions described above, but non of them worked as they suppose to be :) So here is my:
namespace What
{
public enum Color: uint
{
Pink = 1,
Red = 2
}
class The
{
public static void Heck(uint[] array)
{
if (typeof(uint) != array.GetValue(0).GetType())
{
throw new NotImplementedException();
}
}
public static void Main()
{
Color[] colors = new Color[1];
uint[] ints = new uint[1];
ints = (uint[])colors.Clone();
Heck(ints);
}
}
}
P.S. There is also problem with Array when creating non-zero based one dimensional array with Array.CreateInstace(...) method and then try to cast returned object to the one u want. It works for multidimensional, but not for single one. - Anonymous
July 03, 2005
Heck(null) throws the dreaded NullReferenceException. - Anonymous
July 03, 2005
Matt: Nope. It's not that difficult to get this to be thrown
Rick: You got it! Congrats. I'll blog about this behavior later
Stefan: You got it! Too bad you weren't as fast as Rick.
Appwiz: That's not what i asked. I asked when the "PleaseExplainThisToMeException" would eb thrown. I originally wrote this to be more resilient to things like that, but i realized it didn't matter. - Anonymous
July 03, 2005
Um, Cyrus...
Riks example is incorrect and yields a InvalidCastException. int[] can't be cast to uint[].
The cast doesn't work on arrays of different integral types. It only works on arrays with the same integral type (either enums or the actual integer type)
Stefan's example also is not minimal. Cloning the array is not required. All that is required is casting to (Array).
if you have enum unitEnum : uint { None }, then my example works and you can look at my blog. - Anonymous
July 03, 2005
Wesner: my example does work, but I used 2.0b2. I just tried it with 1.1 and it throws an InvalidCastException, as you noted.
Rik - Anonymous
July 04, 2005
Rick: I sow this "feature" in some of Whidbey betas too... - Anonymous
July 04, 2005
Cyrus,
More than the solution, I am pretty curious as to how did you manage to come up with this problem? - Anonymous
July 04, 2005
not related to the solved quiz, but it kind of bugs me that:
if (typeof(uint) != array.GetValue(0).GetType()) {}
is not intuitively readable as:
if (array.GetValue(0).GetType() != typeof(uint) {}
... or maybe it's just me. - Anonymous
July 13, 2005
The comment has been removed - Anonymous
July 14, 2005
What if you do something weird like marshall an array from a different version of the framework.
e.x.: I'm running v1.1 of the framework and I pass in an array marshalled from v1.0.
I'm guessing for two types to be equal, maybe they have to have the same assembly version#.