Using this type:
class Foo
{
public static implicit operator int(Foo obj)
{
return 5;
}
}
var test=new[] { new Foo() };
The following works as expected
var ok=test.Select(x => (int)x).ToList();
but using Cast<> fails with an InvalidCastException - why?
var fail=test.Cast<int>().ToList();
Read Jon Skeet's blog about reimplementing Linq (EduLinq), specifically part 33, where he says this:
It's worth noting that (as of .NET 3.5 SP1) Cast and OfType only perform reference and unboxing conversions. They won't convert a boxed int to a long, or execute user-defined conversions. Basically they follow the same rules as converting from object to a generic type parameter. (That's very convenient for the implementation!)
Casting operators are purely C# compiler level features, the run-time doesn't know anything about them so there is no simple way to implement this via generic Cast method. One way to do this is to perform run-time code generation:
public static class Converter<TSource, TResult>
{
static Converter()
{
var sourceParameter = Expression.Parameter(typeof(TSource));
var conversionExpression = Expression.Lambda<Func<TSource, TResult>>(
Expression.Convert(sourceParameter, typeof(TResult)),
sourceParameter);
Instance = conversionExpression.Compile();
}
public static Func<TSource, TResult> Instance
{
get;
private set;
}
}
public static class EnumerableEx
{
public static IEnumerable<TResult> Cast<TSource, TResult>(this IEnumerable<TSource> source)
{
return source.Select(Converter<TSource, TResult>.Instance);
}
}
but then you'll loose compile-time checking:
var test = new[] { new Foo() };
var ok = test.Cast<Foo, int>().ToList(); // compiles and works ok
var error = test.Cast<Foo, double>().ToList(); // compiles but fails at run-time
Another way is to use reflection as in Puzzling Enumerable.Cast InvalidCastException but this will not work with built-in conversions like from int to long.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With