IEnumerable.Cast won't work even if an explicit cast operator is defined?

后端 未结 5 1727
天涯浪人
天涯浪人 2020-12-03 17:20

I have an explicit conversion defined from type Bar to type Foo.

public class Bar
{
  public static explicit operator Foo(Bar bar)
         


        
相关标签:
5条回答
  • 2020-12-03 17:57

    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);
    
    0 讨论(0)
  • 2020-12-03 17:59

    Use Select:

    var manyFoos = manyBars.Select(bar => (Foo)bar);
    
    0 讨论(0)
  • 2020-12-03 18:08

    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.

    0 讨论(0)
  • 2020-12-03 18:11

    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);
    
    0 讨论(0)
  • 2020-12-03 18:12

    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
    
    0 讨论(0)
提交回复
热议问题