【问题标题】:Interface with abstract class与抽象类的接口
【发布时间】:2017-02-03 13:35:52
【问题描述】:

我必须编写一个名为 Vehicle 的类,它具有许多属性(例如大小、座位、颜色……),而且我还有两个类要编写,称为 TrunkCar,它们具有自己的属性。

所以我写了:

// Vehicle.cs
abstract public class Vehicle
{
    public string Key { get; set; }
    ...
}

// Car.cs
public class Car : Vehicle
{
    ...
}

// Trunk.cs
public class Trunk : Vehicle
{
    ...
}

之后,我写了一个接口:

// IVehicleRepository.cs
public interface IVehicleRepository
{
    void Add(Vehicle item);
    IEnumerable<Vehicle> GetAll();
    Vehicle Find(string key);
    Vehicle Remove(string key);
    void Update(Vehicle item);
}

所以我想我可以使用这样的东西:

// CarRepository.cs
public class CarRepository : IVehicleRepository
{
    private static ConcurrentDictionary<string, Car> _cars =
          new ConcurrentDictionary<string, Car>();

    public CarRepository()
    {
        Add(new Car { seats = 5 });
    }

    public IEnumerable<Car> GetAll()
    {
        return _cars.Values;
    }

    // ... I implemented the other methods here

}

但是,我遇到了错误:

错误 CS0738:“CarRepository”未实现接口成员“IVehicleRepository.GetAll()”。 'CarRepository.GetAll()' 无法实现 'IVehicleRepository.GetAll()' 因为它没有匹配的返回类型 'IEnumerable'。

那么,我该怎么做呢?

【问题讨论】:

    标签: c# interface polymorphism abstract


    【解决方案1】:

    您的CarRepository 没有实现该方法。这两个不一样:

    • public IEnumerable&lt;Car&gt; GetAll()
    • IEnumerable&lt;Vehicle&gt; GetAll()

    这是两种不同的类型,当您从接口派生时,您必须准确地实现它。你可以这样实现它:

    public IEnumerable<Vehicle> GetAll()
    {
        // Cast your car collection into a collection of vehicles
    }
    

    但是更好的方法是让它成为一个通用接口:(缺点是这两种不同的实现类型又是两种不同的类型,所以看看这是否是你想要的)

    public interface IVehicleRepository<TVehicle> {}
    public class CarRepository : IVehicleRepository<Car> {}
    

    更完整的版本:

    public interface IVehicleRepository<TVehicle>  where TVehicle : Vehicle
    {
        void Add(TVehicle item);
        IEnumerable<TVehicle> GetAll();
        Vehicle Find(string key);
        Vehicle Remove(string key);
        void Update(TVehicle item);
    }
    
    public class CarRepository : IVehicleRepository<Car>
    {
        private static ConcurrentDictionary<string, Car> _cars =
              new ConcurrentDictionary<string, Car>();
    
        public CarRepository()
        {
            Add(new Car { seats = 5 });
        }
    
        public IEnumerable<Car> GetAll()
        {
            return _cars.Values;
        }
    }
    

    【讨论】:

    • 谢谢你们(stackoverflow.com/users/6400526/gilad-greenstackoverflow.com/users/5528593/ren%C3%A9-vogt)。这对我有帮助,但我遇到了另一个问题。如果我只有一个存储库,我可以将其注入 Startup.cs 上的“public void ConfigureServices(IServiceCollection services)”:services.AddSingleton();但是,现在我有两个存储库:CarRepository 和 TrunkRepository(扩展 IVehicleRepository)。现在如何注入 CarRepository 和 TrunkRepository?
    • @Olavo Shibate - 很高兴它有帮助。如果它帮助您解决了特定问题,请考虑将其标记为已解决。至于另一个问题 - 政策是后续问题应在单独的问题中发布。请搜索人们遇到的类似问题,如果您仍然需要帮助,请发布一个新问题,我们很乐意为您提供帮助
    【解决方案2】:

    您可以将IVehicleRepository 设为通用:

    public interface IVehicleRepository<T> where T : Vehicle
    {
        void Add(T item);
        IEnumerable<T> GetAll();
        Vehicle Find(string key);
        Vehicle Remove(string key);
        void Update(T item);
    }
    

    然后像这样实现类:

    public class CarRepository : IVehicleRepository<Car>
    {
        private static ConcurrentDictionary<string, Car> _cars =
              new ConcurrentDictionary<string, Car>();
    
        public CarRepository()
        {
            Add(new Car { seats = 5 });
        }
    
        public IEnumerable<Car> GetAll()
        {
            return _cars.Values;
        }
    }
    

    但是你仍然会遇到CarRepositoryIVehicleRepository&lt;Car&gt;TruckRepositoryIVehicleRepository&lt;Truck&gt; 的问题。而且这两个接口是不同的类型,只有在variance正确的情况下才能相互分配。

    【讨论】:

      猜你喜欢
      • 2017-02-19
      • 2016-03-24
      • 2010-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多