我有从Bar
类型到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; }
}
然而,当我这样做时:
using System.Linq;
...
var manyFoos = manyBars.Cast<Foo>();
它抛出一个异常,说它无法施放。
如何告诉Cast
使用我的演员来尝试转换?
答案 0 :(得分:9)
Cast运算符是编译器在代码中使用强制转换时调用的静态方法。它们不能动态使用。 Enumerable.Cast
执行两个不受约束的泛型类型的运行时强制转换,因此在编译期间无法知道哪些强制转换器要使用。要做你想做的事,你可以使用Select
:
manyFoos.Select(foo => (Bar)foo);
答案 1 :(得分:4)
linq Cast
方法基本上是一个框和unbox。它不知道C#中定义的隐式或显式转换运算符,编译器会处理标准方法调用。
你必须做这样的事情:
var manyFoos = manyBars.Select(bar => (Foo)bar);
答案 2 :(得分:4)
由于Cast
方法不是generic
,因此在编译时不知道所有其他答案指向类型。它包含object
的类型,并对T
进行显式转换。此操作失败,因为您没有从object
到Foo
的转换运算符。这也是不可能的。
这是一个关于使用动态的工作,其中强制转换将在运行时完成。
public static class DynamicEnumerable
{
public static IEnumerable<T> DynamicCast<T>(this IEnumerable source)
{
foreach (dynamic current in source)
{
yield return (T)(current);
}
}
}
然后像
一样使用它 var result = bars.DynamicCast<Foo>();//this works
答案 3 :(得分:2)
使用Select
:
var manyFoos = manyBars.Select(bar => (Foo)bar);
答案 4 :(得分:1)
您的代码实际上并未编译。我假设“Bar”类中还有一个属性“Gar”?
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>();
}
+
我鼓励你阅读有关协方差的内容。
假设A可转换为B,如果X<A>
可转换为X<B>
,则X是协变的。
使用C#的协方差概念(和逆变),“可转换”意味着可以通过隐式引用转换进行转换 - 例如A子类化B或A实现B.不包括数字转换,装箱转换和自定义转换。
你必须使用接口。