IEnumerable <t>。即使定义了一个显式的强制转换操作符,它也不会工作?</t>

时间:2013-09-23 06:41:04

标签: c#

我有从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使用我的演员来尝试转换?

5 个答案:

答案 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进行显式转换。此操作失败,因为您没有从objectFoo的转换运算符。这也是不可能的。

这是一个关于使用动态的工作,其中强制转换将在运行时完成。

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.不包括数字转换,装箱转换和自定义转换。

你必须使用接口。