Почему я не могу использовать LINQ to Objects, когда мой класс реализует IEnumerable <T>несколько раз? - PullRequest
7 голосов
/ 24 июня 2011

У меня есть интересная проблема, когда класс наследует от класса, который реализует IEnumerable, но я также хочу, чтобы класс реализовал IEnumerable для другого типа.Все работает, за исключением методов расширения IEnumerable, что означает, что я не могу сделать никакой LINQ к объектам по умолчанию, не всегда вызывая сначала.У кого-нибудь есть какие-либо идеи помимо постоянного кастинга?

using System;
using System.Collections.Generic;
using System.Linq;

namespace LinqTesting
{
    public class Trucks<T> : Vehicles, IEnumerable<Truck>
    {    
        public Trucks()
        {    
            // Does Compile
            var a = ((IEnumerable<Truck>)this).FirstOrDefault();
            // Doesn't Compile, Linq.FirstOrDefault not found
            var b = this.FirstOrDefault();
        }    

        public new IEnumerator<Truck> GetEnumerator() { throw new NotImplementedException(); }
    }    

    public class Vehicles : IEnumerable<Vehicle>
    {    
        public IEnumerator<Vehicle> GetEnumerator() { throw new NotImplementedException(); }
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw new NotImplementedException(); }
    }    

    public class Vehicle { }

    public class Truck : Vehicle { }
}     

Ответы [ 5 ]

7 голосов
/ 24 июня 2011

На самом деле вы можете, но вы не можете воспользоваться преимуществами вывода универсальных типов, потому что ваш класс реализует два IEnumerable<T> двух разных типов, и компилятор не может знать, какой тип вы хотите использовать.

Вы можете указать его direclty, например:

var b = this.FirstOrDefault<Truck>();
7 голосов
/ 24 июня 2011

Измените свой код на:

public class Trucks : Vehicles<Truck>
{    
}    

public class Vehicles<T> : IEnumerable<T>
    where T : Vehicle
{    
}    

public class Vehicle { }

public class Truck : Vehicle { }
4 голосов
/ 24 июня 2011

Реализация IEnumerable несколько раз сбивает с толку компилятор, который IEnumerable <> должен учитывать для этого.

IEnumerable<Vehicle> or IEnumerable<Truck>?

this.FirstOrDefault<Truck>() might compile. 
2 голосов
/ 24 июня 2011

Похоже, вы застряли.Вот предложение, чтобы уменьшить ваш набор текста.Вы можете создать метод расширения для некоторых из ваших обычно используемых типов IEnumerable <>.

var a = myList.AsTruckEnumerable().FirstOrDefault();

public static partial class Extensions
{
  public static IEnumerable<Truck> AsTruckEnumerable (this IEnumerable<Truck> trucks)
  {
     return trucks;
  }
}

public class Trucks<T> : Vehicles, IEnumerable<Truck>
{    
   public Trucks()
   {    
      // Does Compile
      var a = ((IEnumerable<Truck>)this).FirstOrDefault();

      // Does compile
      var b = this.AsTruckEnumerable().FirstOrDefault();
      // Doesn't Compile, Linq.FirstOrDefault not found
      //var b = this.FirstOrDefault();
   }    

   public new IEnumerator<Truck> GetEnumerator() { throw new NotImplementedException(); } 
}    
0 голосов
/ 24 июня 2011

публичный новый IEnumerator GetEnumerator ()

Это ключевое слово new в этой строке скрывает метод GetEnumerator (), унаследованный от класса Vehicle. Я не уверен, что это сработает, но, возможно, вместо этого попробуйте явная реализация интерфейса .

...