Reputation: 33870
I have an explicit conversion defined from type Bar
to type Foo
.
public class Bar
{
public static explicit operator Foo(Bar bar)
{
return new Foo(bar.Gar);
}
}
public class Foo
{
public string Gar { get; set; }
public Foo() { }
public Foo(string gar) { Gar = gar; }
}
However, when I do:
using System.Linq;
...
var manyFoos = manyBars.Cast<Foo>();
It throws an exception saying it can't cast.
How do I tell Cast
to use my cast operator to try the conversion?
Upvotes: 15
Views: 3648
Reputation: 22749
Conversion operators are static methods that the compiler calls when you use casts in code. They cannot be used dynamically. Enumerable.Cast
does a runtime cast of two unconstrained generic types, so it cannot know during compile time which cast operators to use. To do what you want, you can use Select
:
manyFoos.Select(foo => (Bar)foo);
Upvotes: 13
Reputation: 73492
As all other answers pointed type is not known in compile time since Cast
method is not generic
. It holds type of object
and makes a explicit cast to T
. this fails because you don't have conversion operator from object
to Foo
. And that is not possible also.
Here is a work around using dynamics in which cast will be done in runtime.
public static class DynamicEnumerable
{
public static IEnumerable<T> DynamicCast<T>(this IEnumerable source)
{
foreach (dynamic current in source)
{
yield return (T)(current);
}
}
}
Then use it like
var result = bars.DynamicCast<Foo>();//this works
Upvotes: 5
Reputation: 123
Your code doesn't actually compile. I assume that there is a property "Gar" in the "Bar" class as well?
public class Bar
{
public string Gar { get; set; }
public static explicit operator Foo(Bar bar)
{
return new Foo(bar.Gar);
}
}
public class Foo
{
public string Gar { get; set; }
public Foo() { }
public Foo(string gar) { Gar = gar; }
}
static void Main(string[] args)
{
List<Bar> bars = new List<Bar>();
for (int i = 0; i < 10; i++)
bars.Add(new Bar() { Gar = i.ToString() });
var result = bars.Cast<Foo>();
}
+
I encaurage you to read about covariance.
Assuming A is convertible to B, X is covariant if X<A>
is convertible to X<B>
.
With C#’s notion of covariance (and contravariance), “convertible” means convertible via an implicit reference conversion— such as A subclassing B, or A implementing B. Numeric conversions, boxing conversions, and custom conversions are not included.
You have to do that with interfaces.
Upvotes: 1
Reputation: 149030
The linq Cast
method essentially does a box and unbox. It is not aware of either implicit or explicit cast operators defined in C#, which the compiler treats standard method calls.
You'd have to do something like this:
var manyFoos = manyBars.Select(bar => (Foo)bar);
Upvotes: 6