如何使用子泛型接口实现通用泛型接口

3
我在实现泛型的父子接口时遇到了问题。目前最好的答案是:这是不可能的,但我也没有找到其他人问过完全相同的问题。我希望只是因为我不知道正确的语法,以使编译器理解我的意图。以下是我试图实现的代码示例(已经简化)。
public interface I_Group<T>
    where T : I_Segment<I_Complex>
{
    T Segment { get; set; }
}

public interface I_Segment<T>
    where T : I_Complex
{
    T Complex { get; set; }
}

public interface I_Complex
{
    string SomeString { get; set; }
}

public partial class Group : I_Group<Segment>
{   
    private Segment segmentField;

    public Group() {
        this.segmentField = new Segment();
    }

    public Segment Segment {
        get {
            return this.segmentField;
        }
        set {
            this.segmentField = value;
        }
    }
}

public partial class Segment : I_Segment<Complex> {

    private Complex complexField;

    public Segment() {
        this.complexField = new Complex();
    }

    public Complex Complex {
        get {
            return this.c_C001Field;
        }
        set {
            this.c_C001Field = value;
        }
    }
}

public partial class Complex : I_Complex {

    private string someStringField;

    public string SomeString {
        get {
            return this.someStringField;
        }
        set {
            this.someStringField = value;
        }
    }
}

在这里,Complex是实现了I_Complex接口的子类,没有错误。Segment是它的父类,也实现了I_Segment接口而没有错误。问题出在祖先类Group上,试图实现I_Group接口时出现了错误。

The type 'Segment' cannot be used as type parameter 'T' in the generic type or method 'I_Group<T>'. There is no implicit reference conversion from 'Segment' to 'I_Segment<I_Complex>'.

我认为这是一个协变性问题,但我也被告知这应该在C# 4.0中起作用。当子类不是泛型时,它可以工作,这让我想到必须存在一些语法来正确编译它。我做错了什么吗?这可行吗?如果不行,有人能帮我理解为什么吗?


你的Segment定义在哪里? - chtenb
它在那里,你往下翻了吗? - Kyle Moyer
如果您编写类似于以下代码段:public partial class Segment : I_Segment<I_Complex>,会发生什么? - chtenb
请不要在 I 和名称之间加下划线,这是一种不好的编程风格。 - Felix K.
@Chiel92 虽然这段代码可以编译,但需要将成员更改为接口类型,而不是显式的类类型。这最终破坏了我已经编写好的使用这些类的代码。 - Kyle Moyer
2个回答

2
您可以在I_Group接口声明中添加第二个通用类型参数:
public interface I_Group<T, S>
    where T : I_Segment<S>
    where S : I_Complex
{
    T Segment { get; set; }
}

Group 类的声明中明确指定两种类型:

public partial class Group : I_Group<Segment, Complex>

它将使您的代码编译。


这正是我正在寻找的。在修改我的接口和类一小时后,它成功编译了,没有任何问题。非常感谢! - Kyle Moyer

0

要使用协变性或逆变性与接口配合,可以使用"in"和"out"关键字。举个例子,协变性使用了out关键字:

public interface A<out T>
{
    T Foo();
}

逆变使用 in 关键字:

public interface B<in T>
{
    Bar( T t );
}

在您的情况下,问题在于您的I_Segment接口既不是协变的也不是逆变的,因此I_Segment与I_Segment不兼容,这就是为什么会出现编译错误的原因。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接