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?
Cast 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);
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);
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
使用Select
:
var manyFoos = manyBars.Select(bar => (Foo)bar);
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.