Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement a generic interface with a child generic interface

I'm having an issue with implementing parent/child interfaces when both of them are generic. The best answer I've been able to find is that it isn't possible, but I also haven't been able to find anyone else asking the exact same question. I'm hoping that I just don't know the right syntax to make the compiler understand what I'm trying to do. Here is a stripped down example of the code I'm trying to implement.

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;
        }
    }
}

So here, Complex is the grandchild, which implements I_Complex without error. Segment is its parent, which implements I_Segment without error. The issue is with the grandparent, Group, trying to implement I_Group. I get the error

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>'.

I am led to believe this is an issue with covariance, but I was also led to believe this was something that was supposed to work in C# 4.0. This works when the child isn't generic, which leads me to think that there must exist some syntax to get this to compile properly. Am I doing something wrong? Is this even possible? And if not, could someone help me understand why not?

like image 225
Kyle Moyer Avatar asked Apr 18 '26 01:04

Kyle Moyer


1 Answers

You can add second generic type parameter into I_Group interface declaration:

public interface I_Group<T, S>
    where T : I_Segment<S>
    where S : I_Complex
{
    T Segment { get; set; }
}

And specify explicitly both types in Group class declaration:

public partial class Group : I_Group<Segment, Complex>

It will make your code compile.

like image 183
MarcinJuraszek Avatar answered Apr 19 '26 13:04

MarcinJuraszek



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!