C# 如何将接口方法的返回类型定义为另一个接口?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/650663/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 11:48:50  来源:igfitidea点击:

How do I define the return type of an interface method to be another interface?

c#interface

提问by David Conlisk

I'm new to interfaces and abstract classes. I want to create a couple of interfaces to define core methods and variables for the objects for a shopping cart system. Then I want to create abstract classes which implement the core functions. The idea is that they can be used by other classes in slightly different ways for different projects.

我是接口和抽象类的新手。我想创建几个接口来为购物车系统的对象定义核心方法和变量。然后我想创建实现核心功能的抽象类。这个想法是它们可以被其他类以稍微不同的方式用于不同的项目。

Here are my (cut-down) interfaces:

这是我的(缩减)界面:

public interface ICart
{
    ...
    List<ICartItem> CartItems { get; set; }
}

public interface ICartItem
{
    int ProductId { get; set; }
    int Quantity { get; set; }
}

And here is my abstract Cart class (again, only showing relevant lines) which implements ICart:

这是我实现 ICart 的抽象 Cart 类(同样,只显示相关行):

public abstract class Cart : ICart
{

    private List<CartItem> _cartItems = new List<CartItem>();

    public List<CartItem> CartItems 
    {
        get
        {
            return _cartItems;
        }
    }
}

And my CartItem class which implements ICartItem:

我的 CartItem 类实现了 ICartItem:

public abstract class CartItem : ICartItem
{
    ...
}

When I try to compile the classes I get an error saying: 'Cart' does not implement interface member 'CartItems'. 'Cart.CartItems' cannot implement 'ICart.CartItems' because it does not have the matching return type of System.Collections.Generic.List<ICartItem>.

当我尝试编译这些类时,我收到一条错误消息:“Cart”没有实现接口成员“CartItems”。'Cart.CartItems' 无法实现 'ICart.CartItems',因为它没有 System.Collections.Generic.List<ICartItem> 的匹配返回类型。

I thought that the idea here is that the interface can be implemented by a number of classes which perform the core functions in different ways and add new methods, etc. Why would my interface need to know what class is actually being used, just as long as that class actually implements the interface correctly?

我认为这里的想法是接口可以由许多类来实现,这些类以不同的方式执行核心功能并添加新方法等。 为什么我的接口需要知道实际使用的是什么类,只要因为那个类实际上正确地实现了接口?

采纳答案by Tamas Czinege

You need to user generics in C# 2 to achieve that:

您需要在 C# 2 中使用泛型来实现:

public interface ICart<T> where T : ICartItem
{
    // ...
    List<T> CartItems { get; set; }
}

public abstract class Cart : ICart<CartItem>
{
    // ...
    public List<CartItem> CartItems { get; set; }
}

回答by Jamie Ide

ICart specifies a getter and setter for CartItems but your implementation only has a get.

ICart 为 CartItems 指定了一个 getter 和 setter,但您的实现只有一个 get。

回答by Frederik Gheysels

In your abstract class, you should define that the return type of the CartItems property, is of type List<ICartItem>.

在您的抽象类中,您应该定义 CartItems 属性的返回类型是 type List<ICartItem>

But, if you really want that the property is of type List<CartItem>, you can maybe do this:

但是,如果您真的希望该属性为 type List<CartItem>,您可以这样做:

public interface ICart<TCartItem> where TCartItem : ICartItem
{
   List<TCartItem> CartItems { get; set; }
}

public interface ICartItem
{
}

public abstract class Cart : ICart<CartItem>
{
     public List<CartItem> { get; set; }
}

public abstract class CartItem : ICartItem
{
}

回答by Reed Copsey

This is a matter of contra/covariance.

这是一个反/协方差问题。

2 changes are required to make this compile.

进行此编译需要进行 2 次更改。

1) Remove the "set" option on the property of the interface. (It's only implementing a get; property, which makes the most sense, in any case)

1)去掉接口属性上的“设置”选项。(它只是实现了一个 get; 属性,这在任何情况下都是最有意义的)

2) Change Cart to:

2) 将购物车更改为:

public abstract class Cart : ICart
{

private List<CartItem> _cartItems = new List<CartItem>();

public List<ICartItem> CartItems 
{ ...

I also highly recommend changing your interface to expose IList instead of List. The design guidelines (and FxCop) recommend not exposing List in the public interface. List is an implementation detail - IList is the appropriate interface/return type.

我还强烈建议更改您的界面以公开 IList 而不是 List。设计指南(和 FxCop)建议不要在公共接口中公开 List。List 是一个实现细节 - IList 是适当的接口/返回类型。

回答by Joel

An interface is an agreement. A contract, if you will, between you and anyone who uses your class. By telling folks that you are implementing the ICart interface, you are promising them that all the methods in the interface exist on your class. Thus, all your methods must match the signatures of the interface methods.

一个接口就是一个协议。您与使用您的课程的任何人之间的合同,如果您愿意的话。通过告诉人们您正在实现 ICart 接口,您向他们保证接口中的所有方法都存在于您的类中。因此,您的所有方法都必须与接口方法的签名相匹配。

In order to return of list of items that implementICartItem, you need to use generics as suggested by DrJokepu. This tells everyone that the interface only gurentees a list of objects that implement ICartItem, not ICartItem specifically.

为了返回实现ICartItem的项目列表,您需要使用 DrJokepu 建议的泛型。这告诉每个人,接口只保证实现 ICartItem 的对象列表,而不是专门的 ICartItem。

public interface ICart<T> where T : ICartItem
{
    List<T> CartItems { get; set; }
}

回答by Eric

There are 2 ways to accomplish this. You can either use generics or explicitly implement interface members.

有两种方法可以实现这一点。您可以使用泛型或显式实现接口成员。

Generics

泛型

public interface ICart<TCartItem> where TCartItem : ICartItem
{
    ...
    List<TCartItem> CartItems { get; set; }
}

public interface ICartItem
{
    int ProductId { get; set; }
    int Quantity { get; set; }
}

public abstract class Cart : ICart<CartItem>
{

    private List<CartItem> _cartItems = new List<CartItem>();

    public List<CartItem> CartItems 
    {
        get
        {
            return _cartItems;
        }
    }
}
public abstract class CartItem : ICartItem
{
    ...
}

Explicitly implemented members

显式实现的成员

public interface ICart
{
    ...
    List<ICartItem> CartItems { get; set; }
}
public interface ICartItem
{
    int ProductId { get; set; }
    int Quantity { get; set; }
}

public abstract class Cart : ICart
{
    private List<CartItem> _cartItems = new List<CartItem>();

    List<ICartItem> ICart.CartItems
    {
       get
       {
           return CartItems;
       }
    }
    public List<CartItem> CartItems 
    {
        get
        {
            return _cartItems;
        }
    }
}
public abstract class CartItem : ICartItem
{
    ...
}