Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
464 views
in Technique[技术] by (71.8m points)

c# - Why an inherited interface can't be converted to its base interface in generic context?

I'm trying to implement an interface inheritance system in my C# project, but I can't get it to work.

Here is a simplified version:

public interface BaseInterface {}

public abstract class AbstractClass<T> where T : BaseInterface {}

public interface ChildInterface : BaseInterface {}

public class ConcreteClass : AbstractClass<ChildInterface> {}

I want to use it as follow:

AbstractClass<BaseInterface> c = new ConcreteClass();

The last line of code gives me the following error:

Cannot implicitly convert type 'ConcreteClass' to 'AbstractClass<BaseInterface>'

Why is the conversion impossible?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You aren't able to make the assignment because the base class, AbstractClass<T>, is invariant. What you want to be able to make that kind of assignment is a covariant type. Defining Covariance and Contravariance is limited to interfaces, so that means we need another interface.

public interface IAbstractClass<out T> where T : BaseInterface { }  
public abstract class AbstractClass<T> : IAbstractClass<T> where T : BaseInterface { }

The out keyword marks the generic type parameter as covariant. We then implement that interface in AbstractClass<T>, and our other types can work expected through the interface. These are also the only alterations we need to make, we leave the other type definitions the same:

public interface BaseInterface { }
public interface ChildInterface : BaseInterface { }

public class ConcreteClass : AbstractClass<ChildInterface> { }

We now have a covariant interface that AbstractClass<T> implements, and you can do the kind of assignment you desire, but you'll have to target the IAbstractClass interface.

public void Main() {
    IAbstractClass<BaseInterface> c = new ConcreteClass();
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...