IEnumerable.即使定义了显式强制转换运算符,强制转换也不起作用
本文关键字:转换 运算符 不起作用 定义 IEnumerable | 更新日期: 2023-09-27 18:32:33
我有一个从类型 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
使用我的投射运算符来尝试转换?
转换运算符是在代码中使用强制转换时编译器调用的静态方法。它们不能动态使用。 Enumerable.Cast
执行两个不受约束的泛型类型的运行时强制转换,因此它在编译时无法知道要使用哪个强制转换运算符。要做你想做的事,你可以使用 Select
:
manyFoos.Select(foo => (Bar)foo);
linq Cast
方法本质上是一个盒子和取消一个盒子。它不知道 C# 中定义的隐式或显式强制转换运算符,编译器会处理这些运算符的标准方法调用。
你必须做这样的事情:
var manyFoos = manyBars.Select(bar => (Foo)bar);
由于所有其他答案指向类型在编译时都未知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
使用 Select
:
var manyFoos = manyBars.Select(bar => (Foo)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 是协变的,如果 X<A>
可转换为 X<B>
。
在 C# 的协方差(和逆变)概念中,"可转换"意味着可通过隐式引用转换进行转换,例如 A 子类化 B 或实现 B 的 A。
你必须用接口来做到这一点。