简体   繁体   中英

Casting interface with generic parameter implemented by class without generic parameter

I have two interfaces,

public interface IDocument<SegType> where SegType : ISegment

and

public interface ISegment

Basically, I want to enforce that each class that implements IDocument is composed of one type of ISegment , and that people using these classes never need to know about which type of ISegment their class uses internally.

I then created a class that implements IDocument<SegType> where SegType : ISegment :

public class MyDocument : IDocument<MySegment>

and the corresponding MySegment :

public class FffSegment : ISegment

All of this compiles and works just as I expect it to when I specify MyDocument as the type. Why can I not implicitly cast an instance of MyDocument to be of type IDocument<Isegment> ? When I try the line:

IDocument<ISegment> doc = new MyDocument();

I get the error

Cannot implicitly convert type 'MyDocument' to 'IDocument<ISegment>'. An explicit conversion exists (are you missing a cast?)

But when I cast it, it just comes back null. If I change it to:

IDocument<MySegment> doc = new MyDocument();

it works, as it does when I change the class definition to

public class MyDocument : IDocument<ISegment>

Why can I not force a specific type that implements ISegment for that implementation of IDocument? I want to re-use this code for different types of IDocument and ISegment and maybe some day some implementations of IDocument will allow for multiple types of ISegment but MyDocument should be restricted against this kind of behavior. How can I enforce these requirements but still write code that is generic enough to be re-used in the future?

You need to get into the nastiness of co-and-contra variance:

public interface IDocument<out SegType> where SegType : ISegment
{}

I think that should make your example compile now...

Here's some reading material:

Because IDocument<MySegment> cannot cast directly to an IDocument<ISegment> . If it could, you could do this:

IDocument<ISegment> doc1 = new IDocument<MySegment>;
doc1.Add(new MyOtherSegment());   // invalid

(Assuming IDocument<T> has an Add(T newSegment) method)

Take a long look at your design and decide if generics are really necessary or if just using ISegment within IDocument is sufficient.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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