0

I'm trying to cast a list of byte to a list of ints.

My List of bytes only contains one value 11.

tmpMarketRights = AllMarketRights.Cast<int>().ToList();

11 should be able to be casted to an INT does anyone know why this cast is invalid, and the shortest way to cast a list of bytes to a list of int?

2 Answers2

5

Reason of this exception?

Firstly, let's try this:

 byte myByte = 11;
 object myObject = myByte;
 int x = (int)myObject; // Exception will be thrown here

As you see, InvalidCastException will be thrown. Because, a boxed value can only be unboxed to a variable of the exact same type.

Now, let's see what is Cast() doing. You can look at the implementation of this method here. As you see, it will return CastIterator. And here is the implementation of the CastIterator:

static IEnumerable<TResult> CastIterator<TResult>(IEnumerable source) 
{
     foreach (object obj in source) yield return (TResult)obj;
}

As you see, it doesn't cast byte to int, but object to int. The reason of this is that, Cast is an extension method for IEnumerable, not IEnumerable<T>.

public static IEnumerable<TResult> Cast<TResult>(
    this IEnumerable source
)

So use one of these ways:

 var tmpMarketRights = AllMarketRights.Select(x => Convert.ToInt32(x)).ToList();
 var tmpMarketRights = AllMarketRights.Select(x => (int)x).ToList();
Farhad Jabiyev
  • 26,014
  • 8
  • 72
  • 98
  • 1
    You can cast `byte` to `int` without problem. – Dirk Feb 11 '15 at 18:47
  • why does boxing work on the select as seen in ie's example (x => (int)x) –  Feb 11 '15 at 18:54
  • 1
    @Space, there is no boxing in `(x => (int)x) `, Boxing would involve a conversion between value type and reference type. `Cast` is throwing the exception because of boxing in `foreach (object obj in source)` , where a `byte` type is first converted to `object` and then later `int` in `return (TResult)obj`. – Habib Feb 11 '15 at 18:59
  • @Space As Habib stated, there is not any boxing operation. Because, both `int` and `byte` are value types. – Farhad Jabiyev Feb 11 '15 at 19:05
2

The following will work:

AllMarketRights.Select(x => (int)x).ToList();

To understand why Cast<int> produces an exception, we can look into its implementation:

public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source) { 
    IEnumerable<TResult> typedSource = source as IEnumerable<TResult>;
    if (typedSource != null) return typedSource; 
    if (source == null) throw Error.ArgumentNull("source");
    return CastIterator<TResult>(source);
}

static IEnumerable<TResult> CastIterator<TResult>(IEnumerable source) {
    foreach (object obj in source) yield return (TResult)obj; 
} 

As we can see the CastIterator does not try to cast byte to int (where numeric explicit cast can be applied), but object (where unbox actually should happens, and boxed byte can not be unboxed as int).

ie.
  • 5,982
  • 1
  • 29
  • 44