3

In some library I create I have to use following cast:

public void Foo(IList<uint> uintsList) // I need to use uint in the interface for this method
{
    List<double> doublesList = uintsList.Cast<double>().ToList();
    // Do something with the doublesList
}

I assumed that cast uint -> double should be always valid, and during my test it always worked fine.

But in the application, which uses this method the InvalidCastException occured. Unfortunately I do not have access to this application. So here are my questions:

  • What could cause this exception occured? Isn't the cast uint->double always valid?
  • How can I secure my algorithm to avoid this exception?

EDIT
Of course, before casting I always perform check to avoid situation when uintsList is null or empty

EDIT 2 OK, the problem is solved, I changed the cast using the ConvertAll method, but still I don't understand how it could happen?
So this question still bothers me: how the same part of the code could run properly at my computer, and throw an exception at another? Different compiler/environment versions? Some specific settings? Can anyone tell me where should I seek for the reasons of this situation to avoid it in the future?

Gacek
  • 10,184
  • 9
  • 54
  • 87
  • "So this question still bothers me: how the same part of the code could run properly at my computer, and throw an exception at another?" What exactly is running fine on one computer and is problematic on another? If you think `.ConvertAll(i => (double)i)` is behaving like `.Cast`, that's not true. They are fundamentally different things. `.ConvertAll` simply passes each item to the delegate passed to it and you are *manually* passing a function that takes a `uint` and returns a `double` whereas `.Cast` tries to do the cast itself which fails for the reason I mentioned in my answer. – Mehrdad Afshari Mar 01 '10 at 16:45
  • Yes, I understand that and I see where I made the mistake. But the question is why the mistake occured? Why it worked in my environment (even if it was wrong) and failed (as expected) in the other, how to catch that kind of errors? – Gacek Mar 01 '10 at 17:17
  • Maybe it didn't really occur :) Can you reproduce it? Are you sure you weren't checking against a different build of your binary or things like that? – Mehrdad Afshari Mar 01 '10 at 18:27
  • No, I'm sure. My friend just created a list with 3 uints, used it in my function and it crashed. I copied/pasted his code to my environment, and it worked. I'm a bit confused... – Gacek Mar 02 '10 at 10:53

2 Answers2

6

.Cast method is not meant to perform type conversion like that. It just performs conversions in the inheritance hierarchy.

The reason for this behavior is that the extension method signature takes an IEnumerable and not IEnumerable<T>. Consequently, getting the Current property of the enumerator returns an object to the Cast method. Of course, you can't unbox a value type of one type to another type directly. Basically, Cast will do something like:

int i = 42;
object o = i;
double d = (double)o; // fails.
Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
5

See: C# Converting List<int> to List<double>

The cast uint -> double is valid, but you are casting a list of uints to a list of doubles. On most architectures the lists won't even the same size (in bytes) - you will need to create an entirely new list and cast each element individually. I would use ConvertAll:

List<double> doublesList = uintsList.ConvertAll(x => (double)x);
Community
  • 1
  • 1
rjh
  • 49,276
  • 4
  • 56
  • 63
  • 4
    "On most archetectures the lists won't even the same size (in bytes)" This is totally irrelevant. The OP is *not casting* a `List` to `List`. He is calling the `Enumerable.Cast` method passing a `List`. It takes a sequence and tries to cast each **individual element** of the list and generates a sequence of new type. It's totally different from casting a `List` to `List`. – Mehrdad Afshari Feb 28 '10 at 17:39