简体   繁体   English

通用接口的非通用实现

[英]Non-generic implementations of generic interfaces

I have the following group of 3 interfaces and 3 implementations of those said interfaces. 我具有以下3组接口和这些接口的3种实现。 The interfaces are defined with generics, and the topmost interface requires its parameter to extend the second one down; 接口是用泛型定义的,最顶层的接口需要其参数来向下扩展第二个接口; same with the second interface to the third. 与第二个界面到第三个相同。 The classes have no generic parameters and instead implement the interface with a specific class, each of which meets the requirements for the interface. 这些类没有通用参数,而是使用一个特定的类来实现接口,每个类都满足该接口的要求。

namespace GenericsIssueExample
{
    interface IGroup<Row> where Row : IRow<IEntry>
    {
        Row[] Rows {
            get;
            set;
        }
    }

    interface IRow<Entry> where Entry : IEntry
    {
        Entry[] Entries {
            get;
            set;
        }
    }

    interface IEntry
    {
        int Value {
            get;
            set;
        }
    }

    class ExampleGroup : IGroup<ExampleRow>
    {
        private ExampleRow[] rows;

        public ExampleRow[] Rows {
            get { return rows; }
            set { rows = value; }
        }
    }

    class ExampleRow : IRow<ExampleEntry>
    {
        private ExampleEntry[] entries;

        public ExampleEntry[] Entries {
            get { return entries; }
            set { entries = value; }
        }
    }

    class ExampleEntry : IEntry
    {
        private int val = 0;

        public int Value {
            get { return val; }
            set { val = value; }
        }
    }
}

When I try to compile the above code, I get the following compile error: 当我尝试编译以上代码时,出现以下编译错误:

The type 'GenericsIssueExample.ExampleRow' cannot be used as type parameter 'Row' in the generic type or method 'GenericsIssueExample.IGroup<Row>'. There is no implicit reference conversion from 'GenericsIssueExample.ExampleRow' to 'GenericsIssueExample.IRow<GenericsIssueExample.IEntry>'.

This error is on line 27, which is the definition of ExampleGroup : 此错误在第27行,它是ExampleGroup的定义:

class ExampleGroup : IGroup<ExampleRow>

I don't understand why this is occurring, as ExampleRow does implement IRow<IEntry> . 我不明白为什么会这样,因为ExampleRow确实实现了IRow<IEntry> ( IRow<ExampleEntry> ). IRow<ExampleEntry> )。

How would I correct the above code to resolve that error? 我将如何纠正上述代码来解决该错误?

Just because ExampleEntry can be implicitly converted to an IEntry does not mean that an IRow<ExampleEntry> can be converted to an IRow<IEntry> . 仅仅因为ExampleEntry可以隐式转换为IEntry并不意味着IRow<ExampleEntry>可以转换为IRow<IEntry> If IRow is covariant with respect to its generic argument, then yes, that would be possible, but it's not as it stands, so the implicit conversion isn't possible. 如果IRow相对于其通用参数是协变的,则可以,这是可能的,但事实并非如此,因此隐式转换是不可能的。

If you could implicitly convert an IRow<ExampleEntry> to an IRow<IEntry> then you could set the Entries property to an array of an IEntry type that is not an ExampleRow . 如果你能隐式转换的IRow<ExampleEntry>IRow<IEntry>那么你可以设置Entries属性设置为一个数组IEntry类型,它是不是一个ExampleRow

The problem is you're intermixing interfaces and generics where it is not applicable. 问题是您在不适用的地方混合了接口和泛型。 It's hard to see in your example but if you fix the naming convention so all generic type parameters are named TSomething then it'll be clear. 在您的示例中很难看到,但是如果您修改了命名约定,那么所有通用类型参数都被命名为TSomething那么这很清楚。

Once we do this, then it's clear we want to specify that we want a row of classes that implement IEntry , not a row of IEntry instances themselves. 完成此操作后,很明显,我们要指定我们要一行实现IEntry的类,而不是一行IEntry实例本身。

Here's a working example: 这是一个工作示例:

namespace GenericsIssueExample
{
    interface IGroup<TRow, TEntry>
        where TRow : IRow<TEntry>
        where TEntry : IEntry 
    {
        TRow[] Rows
        {
            get;
            set;
        }
    }

    interface IRow<TEntry> where TEntry : IEntry
    {
        TEntry[] Entries
        {
            get;
            set;
        }
    }

    interface IEntry
    {
        int Value
        {
            get;
            set;
        }
    }

    class ExampleGroup : IGroup<ExampleRow, ExampleEntry>
    {
        private ExampleRow[] rows;

        public ExampleRow[] Rows
        {
            get { return rows; }
            set { rows = value; }
        }
    }

    class ExampleRow : IRow<ExampleEntry>
    {
        private ExampleEntry[] entries;

        public ExampleEntry[] Entries
        {
            get { return entries; }
            set { entries = value; }
        }
    }

    class ExampleEntry : IEntry
    {
        private int val = 0;

        public int Value
        {
            get { return val; }
            set { val = value; }
        }
    }
}

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

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