在 C# 中,为什么我不能从接口签名将基接口类型作为其返回类型的函数返回派生接口类型?

时间:2021-05-20 21:01:02

标签: c#

我收到编译错误: 错误 CS0535 'COITemplateWriter' 没有实现接口成员 'iTemplateWriter.Write(iTemplateModel)' TemplateService 对于以下代码:

    public COITemplate Write(COITemplateModel model)
    {
        throw new NotImplementedException();
    }

上述方法的接口签名如下:

public interface iTemplateWriter
{
    public iTemplate Write(iTemplateModel model);
}

类型COITemplate实现了iTemplate接口,类型COITemplateModel实现了iTemplateModel接口,那么这段代码为什么会失败呢?如果接口要求该方法返回实现 iTemplate 的任何内容并将任何实现 iTemplateModel 的参数作为参数,这难道不是合理的吗?

2 个答案:

答案 0 :(得分:2)

您混淆了在运行时您可以做什么与编译器在编译时需要知道的内容。

这就是泛型在 C# 中的用途

看起来您想要一个接口 iTemplateWriter,您希望能够在其中使用此方法 Write 来接收任何 iTemplateModel 并返回任何 iTemplate

您可以通过两种方式执行此操作:

方法 1 - 您可以在接口级别定义 iTemplateModel 的类型以及接口的实现者将使用的 iTemplate 类型:

    public interface iTemplateWriter<TTemplate, TTemplateModel> 
        where TTemplate : iTemplate
        where TTemplateModel : iTemplateModel
    {
         TTemplate Write(TTemplateModel model);
    }

这样做将允许您定义使用 COITemplateWritterCOITemplateCOITemplateModel

public class COITemplateWritter : iTemplateWriter<COITemplate, COITemplateModel>
{
    public COITemplate Write(COITemplateModel model)
    {
        throw new System.NotImplementedException();
    }
}

如果您在编译时知道实现类需要使用什么类类型,请使用方法 1

如果您需要您的实现类在运行时处理所有类型,而您在编译时不知道类型,则使用方法 2:

方法 2 - 您可以在方法级别定义该方法将使用什么类型的 iTemplate 和什么类型的 iTemplateModel。这将要求所有实现类能够返回在运行时传入的任何类型,这提供了更大的灵活性,但在编译时结构化程度较低。

public interface iTemplateWriter
{
    TTemplate Write<TTemplate, TTemplateModel>(TTemplateModel model)
        where TTemplate : iTemplate
        where TTemplateModel : iTemplateModel;
}

public class COITemplateWritter : iTemplateWriter
{
    public TTemplate Write<TTemplate, TTemplateModel>(TTemplateModel model)
        where TTemplate : iTemplate
        where TTemplateModel : iTemplateModel
    {
        
        throw new System.NotImplementedException();
    }
}

答案 1 :(得分:0)

没有看到 COITemplate 的其余部分,假设它不是一个接口,你应该只需要让函数返回接口类型本身。

package pluralsight.com.horizontalrecyclerview;
...

import de.hdodenhof.circleimageview.CircleImageView;

/**
* Created by User on 2/12/2018.
*/

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {

private static final String TAG = "RecyclerViewAdapter";

//vars
private ArrayList<String> mNames = new ArrayList<>();
private ArrayList<Integer> mImageDrawable = new ArrayList<>();
private Context mContext;

public RecyclerViewAdapter(Context context, ArrayList<String> names, ArrayList<Integer> imageDrawable) {
    mNames = names;
    mImageDrawable = imageDrawable;
    mContext = context;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_listitem, parent, false);
    return new ViewHolder(view);
}

@Override
public void onBindViewHolder(ViewHolder holder, @SuppressLint("RecyclerView") final int position) {
    Log.d(TAG, "onBindViewHolder: called.");

    Glide.with(mContext)
            .asBitmap()
            .load(mImageDrawable.get(position))
            .into(holder.image);

    holder.name.setText(mNames.get(position));

    holder.image.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Log.d(TAG, "onClick: clicked on an image: " + mNames.get(position));
            Toast.makeText(mContext, mNames.get(position), Toast.LENGTH_SHORT).show();
        }
    });
}

@Override
public int getItemCount() {
    return mImageDrawable.size();
}

public class ViewHolder extends RecyclerView.ViewHolder{

    CircleImageView image;
    TextView name;

    public ViewHolder(View itemView) {
        super(itemView);
        image = itemView.findViewById(R.id.image_view);
        name = itemView.findViewById(R.id.name);
    }
  }
}
相关问题