简体   繁体   English

C#使用泛型和接口实现

[英]C# Using generics and interface implementation

Context: .NET 4.0, C# 上下文:.NET 4.0,C#

I'm creating a set of interfaces and a set of clases that implement them to provide some service. 我正在创建一组接口和一组实现它们以提供某些服务的clases。 The clients use the concrete clases but call methods that are declared using the interfaces as parameter types. 客户端使用具体的clases,但调用使用interfaces作为参数类型声明的方法。

A simplified example is this one: 一个简化的例子就是这个:

namespace TestGenerics
{
    // Interface, of fields
    interface IField
    {
    }

    // Interface: Forms (contains fields)
    interface IForm<T> where T : IField
    {

    }

    // CONCRETE CLASES
    class Field : IField
    {   
    }

    class Form <T> : IForm<T> where T : IField
    {
    }

    // TEST PROGRAM
    class Program
    {
        // THIS IS THE SIGNATURE OF THE METHOD I WANT TO CALL
        // parameters are causing the error.
        public static void TestMethod(IForm<IField> form)
        {
            int i = 1;
            i = i * 5;
        }

        static void Main(string[] args)
        {
            Form<Field> b = new Form<Field>();
            Program.TestMethod(b);
        }
    }
}

The code makes sense to me, but I get the compiler error: 代码对我有意义,但我得到编译器错误:

Argument 1: cannot convert from ' TestGenerics.Form<TestGenerics.Field> ' to ' TestGenerics.IForm<TestGenerics.IField> ' TestGenerics 参数1:无法从' TestGenerics.Form<TestGenerics.Field> '转换为' TestGenerics.IForm<TestGenerics.IField> 'TestGenerics

I'm not sure what I'm doing wrong, I've read lots of pages on the internet but none solved my problem. 我不确定我做错了什么,我在互联网上阅读了很多页面,但没有解决我的问题。

Is there a solution that would not modify that much the architecture of what I'm trying to build: 是否有一个解决方案不会修改我正在尝试构建的架构:

Edit:I designed the interfaces in a way such that they should be independent of concrete clases that implement them. 编辑:我设计接口的方式使它们应该独立于实现它们的具体条款。 The concrete clases could be loaded from a dll, but most of the application Works with the interfaces. 具体的clases可以从一个DLL加载,但大多数应用程序与接口一起使用。 In some cases I need to use concrete clases, specially when using clases that need to be serialized. 在某些情况下,我需要使用具体的clases,特别是在使用需要序列化的clases时。

Thanks in advance. 提前致谢。

Alejandro 亚历杭德罗

The problem is that Form<Field> implements IForm<Field> but not IForm<IField> . 问题是Form<Field>实现IForm<Field>而不是IForm<IField> You cannot use an inherited class (or interface) as a generic parameter unless it is marked as covariant with the out identifier. 除非将其标记为与out标识符的协变,否则不能将继承的类(或接口)用作通用参数。 However, marking your interface as covariant will restrict the usage significantly (basically making in an "output-only" interface like IEnumerable ) so it may not work for you. 但是,将您的界面标记为协变将显着限制使用(基本上是在“仅输出”界面,如IEnumerable ),因此它可能不适合您。

One way to get it to work is to make TestMethod generic as well: 让它工作的一种方法是使TestMethod通用的:

public static void TestMethod<T>(IForm<T> form) where T:IField
{
    int i = 1;
    i = i * 5;
}

You can use Covariance, like so: 您可以使用协方差,如下所示:

interface IForm<out T> where T : IField
{

}

More about Covariance and Contravariance here . 有关协方差和逆变的更多信息,请点击此处

Others have pointed out the reasoning behind the error message, but let's examine the design of your sample code for a moment. 其他人已经指出了错误消息背后的原因,但让我们暂时检查一下示例代码的设计。 Perhaps you're using a generic where none is needed. 也许你正在使用一个不需要的通用。

You've already said you're using methods declared in the IField interface, so there may be no need to make your IForm class generic - simply have it store references to IField, instead of the generic argument 'T' (which is already guaranteed to be an IField anyway). 你已经说过你正在使用IField接口中声明的方法,所以可能没有必要让你的IForm类通用 - 只需要存储对IField的引用,而不是通用参数'T'(已经保证)无论如何要成为IField)。

For instance, use: 例如,使用:

public interface IForm
{
    IEnumerable<IField> Fields { get; set; }
}

instead of 代替

public interface IForm<T> where T : IField
{
    IEnumerable<T> Fields { get; set; }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM