C# covariance and inheritance - c#

I'm curious to know why the implementation of my interface in the abstract base class does not satisfy the the requirements in sub-classes. Here's an example:
public interface IBase { }
public interface IConcrete : IBase { }
public interface IBaseManager<out T>
where T : IBase
{
T Create();
IEnumerable<T> SelectAll();
}
public interface IConcreteManager : IBaseManager<IConcrete> { }
public abstract class Base : IBase { }
public class Concrete1 : Base, IConcrete { }
public abstract class BaseManager<T> : IBaseManager<T> where T : class, IBase
{
#region IBaseManager<T> Members
public T Create()
{
throw new NotImplementedException();
}
public IEnumerable<T> SelectAll()
{
throw new NotImplementedException();
}
#endregion
}
public class ConcreteManager : BaseManager<Concrete>, IConcereteManager
{
//error occurs here
}
This is the error that is being generated:
'ConsoleApplication4.ConcreteManager' does not implement interface member 'ConsoleApplication4.IBaseManager<ConsoleApplication4.IConcrete>.Create()'.
'ConsoleApplication4.BaseManager<ConsoleApplication4.Concrete>.Create()' cannot implement 'ConsoleApplication4.IBaseManager<ConsoleApplication4.IConcrete>.Create()' because it does not have the matching return type of 'ConsoleApplication4.IConcrete'.
If I add these methods to the ConcreteManager class, everything is fine and the compiler is happy.
public new IConcrete Create()
{
return base.Create();
}
public new IEnumerable<IConcrete> SelectAll()
{
return base.SelectAll();
}
If simply returning what the methods from the base class return is sufficient, why do the methods have to be added? Why can't the compiler call the methods in the base class?

As John points out correctly, the C# language does not support return type covariance. Neither does the CLR, so even if the language supported it, the only way we could actually implement the feature would be to silently generate exactly the code you've had to add yourself.
The small benefit afforded to developers of avoiding having to write those stub methods really does not justify the considerable cost of doing the more general covariance feature, so we've never done it.

It looks like you're assuming return type covariance, since ConcreteManager (as an IConcreteManager) expects both Create() and SelectAll() methods with a return type of IConcrete and IEnumerable<IConcrete> respectively, which the base class does not provide.
You are getting those errors because C# does not support return type covariance.

When you implement an interface/abstract class, you must use the same signature. See here
Don't let the generics throw you off, this is no different than if there were no generics.

Related

Cannot use LINQ methods on IEnumerable base class from derived class

I am trying to implement IEnumerable<Turtle> in a class deriving from a base class that already implements IEnumerable<Animal>.
Why will calling base.Cast<Turtle>() (or any LINQ method on the base element) in any method from the class Turtle fail to compile?
It is not possible to replace base with this as it obviously results in a StackOverflowException.
Here is a minimal code sample to replicate the issue:
public interface IAnimal {}
public class Animal : IAnimal {}
public class Turtle : Animal {}
public class AnimalEnumerable : IEnumerable<Animal> {
List<Animal> Animals = new List<Animal>();
IEnumerator<Animal> IEnumerable<Animal>.GetEnumerator() {
return Animals.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return Animals.GetEnumerator();
}
}
public class TurtleEnumerable : AnimalEnumerable, IEnumerable<Turtle> {
IEnumerator<Turtle> IEnumerable<Turtle>.GetEnumerator() {
return base.Cast<Turtle>().GetEnumerator(); //FAILS WITH "CANNOT RESOLVE SYMBOL Cast"
}
}
For some reason, replacing base.Cast<Turtle>().GetEnumerator(); with this.OfType<Animal>().Cast<Turtle>().GetEnumerator(); works without throwing a StackOverflowException, but I have no idea why.
There are numerous problems with the code given that other answers get into. I want to answer your specific question:
Why will calling base.Cast<Turtle>() (or any LINQ method on the base element) in any method from the class Turtle fail to compile?
Let's go to the specification, section 7.6.8.
A base-access is used to access base class members that are hidden by similarly named members in the current class or struct.
Are you accessing a base class member? NO. An extension method is a member of the static class that contains the extension method, not the base class.
A base-access is permitted only in the block of an instance constructor, an instance method, or an instance accessor.
You're fine here.
When base.I occurs in a class or struct, I must denote a member of the base class of that class or struct.
Again, Cast<T> is not a member of the base class.
When a base-access references a virtual function member (a method, property, or indexer), the determination of which function member to invoke at run-time (§7.5.4) is changed.
You are not accessing a virtual anything. Extension methods are static.
The function member that is invoked is determined by finding the most derived implementation of the function member with respect to B (instead of with respect to the run-time type of this, as would be usual in a non-base access). Thus, within an override of a virtual function member, a base-access can be used to invoke the inherited implementation of the function member.
So now we see what the purpose of a base access is: to enable a non-virtual dispatch to a virtual member that was overriden in the current type, or to call a base class member that was hidden by a new member in the current type. That is not what you are trying to use base for, and therefore you are doomed to failure. Stop using base off-label like this. Only use it when attempting to do a non-virtual dispatch to a virtual member, or get access to a hidden member.
Eric Lippert has stated before that this was a somewhat conscious design decision here. You were never meant to use extension methods in a case where you have access to the implementation of your base class in the first place.
And if you think about it, you also dont need to do this here. Make a GetEnumerator property or method that is protected and use it! Basic object orientation; no need to torture linq here.
EDIT:
It was pointed out that my previous suggestion did not work. So let me suggest just not implementing two different IEnumerable interfaces as this will cause a lot of headaches with foreach anyway.
I have come to believe that this implementation might be what you actually want:
public interface IAnimal { }
public class Animal : IAnimal { }
public class Turtle : Animal { }
public class AnimalEnumerable : IEnumerable<Animal>
{
IEnumerator<Animal> IEnumerable<Animal>.GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
public class TurtleEnumerable : AnimalEnumerable
{
}
You can then enumerate through Animal and their derivatives all the like
There are several issues with your approach. TurtleEnumerable implements both IEnumerable<Animal> and IEnumerable<Turtle>. To be able to use a TurtleEnumerable instance in a foreach loop you will have to cast it for the code to compile:
foreach (var turtle in (IEnumerable<Turtle>) turtleEnumerable)
You are also using explicit interface implementations to hide the generic GetEnumerator() methods. You have to do that because you cannot do overload resolution on return type alone and the two generic GetEnumerator() methods only differ by return type.
However, this means that a TurtleEnumerable method cannot call the base GetEnumerator() method. The reason for this is that base does not behave like a variable of type "base". Instead it is a reserved word that only can be used to call base class methods. A corollary to this is that extension methods cannot be used with base. Also, you cannot cast base so explicit interface implementations on the base class are not callable through base.
However, you can cast this but because the generic GetEnumerator() on TurtleEnumerable hides the generic GetEnumerator() on AnimalEnumerable you will not be able to call into the base class so you will get a stack overflow because at some point the implementation of TurtleEnumerable.GetEnumerator() will call the same GetEnumerator.
To make your code compile you need to create a protected IEnumerator<Animal> GetEnumerator() method in your base class and create your own TurtleEnumerator class that wraps the base enumerator instance you can get by calling the protected method.
public class TurtleEnumerable : AnimalEnumerable, IEnumerable<Turtle> {
IEnumerator<Turtle> IEnumerable<Turtle>.GetEnumerator() {
return new TurtleEnumerator(base.GetEnumerator());
}
sealed class TurtleEnumerator : IEnumerator<Turtle> {
IEnumerator<Animal> animalEnumerator;
public TurtleEnumerator(IEnumerator<Animal> animalEnumerator) {
this.animalEnumerator = animalEnumerator;
}
public Turtle Current {
get { return (Turtle) animalEnumerator.Current; }
}
Object IEnumerator.Current {
get { return Current; }
}
public Boolean MoveNext() {
return animalEnumerator.MoveNext();
}
public void Reset() {
animalEnumerator.Reset();
}
public void Dispose() {
animalEnumerator.Dispose();
}
}
}
All in all having a collection the implements both IEnumerable<Base> and IEnumerable<Derived> will get you into a lot of trouble. What are you trying to achieve by using this design?
Using a generic List<T> and contravariance you can do things like this:
IEnumerable<Turtle> turtles = new List<Turtle>();
IEnumerable<Animal> animals = (IEnumerable<Animal>) turtles;
You can also replace List<T> by your own generic collection type if that is required.
I will answer to that question:
Why will calling base.Cast() (or any LINQ method on the base
element) in any method from the class Turtle fail to compile?
The reason of that exception is Cast and other such methods are extension methods. And extension methods are static.
For example, let's look at that:
public static class Extensions
{
public static void Method2(this Base b) ...
}
public class Base
{
public void Method1() ...
}
public class Derived:Base
{
public void Test()
{
base.Method1();
base.Method2(); // Does not contain a definition
}
}
And as you know extension methods are a really nice syntactic sugar. They're not really added to the class, but the compiler makes it feel like they are. So, compiler will change that line of code to that one:
Extensions.Method2(base);
If you replace your code with that one the compiler will give more appropriate error message: Use of keyword base is not valid in this context.
As said in MSDN:
A base class access is permitted only in a constructor, an instance
method, or an instance property accessor.
Why are you implementing the IEnumerable on the TurtleEnumerator class? Also, I don't think the accessibility on the AnimalEnumerable when you implemented the IEnumerable interface is correct.
Wouldn't it be implemented something like this:
public interface IAnimal { }
public class Animal : IAnimal { }
public class Turtle : Animal { }
public class AnimalEnumerable : IEnumerable<Animal>
{
protected List<Animal> Animals = new List<Animal>();
public IEnumerator<Animal> GetEnumerator()
{
return Animals.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return Animals.GetEnumerator();
}
}
public class TurtleEnumerable : AnimalEnumerable
{
public void AddTurtle(Turtle turtle)
{
Animals.Add(turtle);
}
public IEnumerable<Turtle> GetTurtles()
{
var iterator = GetEnumerator();
yield return iterator.Current as Turtle;
}
}
[Test]
public void CanAddTurtles()
{
Turtle one = new Turtle();
Turtle two = new Turtle();
TurtleEnumerable turtleStore = new TurtleEnumerable();
turtleStore.AddTurtle(one);
turtleStore.AddTurtle(two);
foreach (var turtle in turtleStore.GetTurtles())
{
// Do something with the turtles....
}
}

Overriding (shadowing, overloading?) methods with different return types in a C# hierarchy

I'm writing an SDK which has an OOP structure for implementing data types;
first an interface
then an abstract implementation
finally an abstract generic implementation
People can choose to implement either the interface, or derive from either of the classes.
public interface IGoo
{
IGoo Duplicate();
...
}
public abstract class Goo : IGoo
{
IGoo IGoo.Duplicate() {
return Duplicate();
}
abstract public Goo Duplicate();
...
}
public abstract class Goo<T> : Goo
{
abstract public Goo<T> Duplicate(); ??????
...
}
I'd like to re-implement the Duplicate method so that it always returns the most specific type possible. I.e. when you call Duplicate on an IGoo instance, you get another IGoo. If you call it on Goo, you get Goo, if you call it on -say- Goo<int>, you get Goo<int>. And all Duplicate() methods always call the most specific implementation.
Is this possible? Is it only possible when you can implement an interface explicitly? In which case, should I not make Goo<int> derive from Goo, but have it implement IGoo instead and type all the low-level functionality twice?
What about the following?
public interface IObj
{
IObj Duplicate();
}
public abstract class Obj : IObj
{
public Obj()
{
}
public virtual IObj Duplicate()
{
return this;
}
}
public abstract class ObjT<T> : Obj
{
public ObjT()
{
}
public override IObj Duplicate()
{
return this;
}
}
public class ObjImpl : Obj
{
}
public class ObjTImpl : ObjT<int>
{
}
I understand that you want it to return the most specific type possible in any inheriting class but it actually is. It's boxing the inheriting type into the interface (or a raw object if you where to return objects instead of interface types. If you run the following test in a console app you will see the proper type is represented:
namespace TestConsole
{
class Program
{
static void Main(string[] args)
{
ObjImpl a = new ObjImpl();
ObjTImpl b = new ObjTImpl();
Console.WriteLine(a.Duplicate().GetType());
Console.WriteLine(b.Duplicate().GetType());
Console.ReadLine();
}
}
}
// outputs:
// ObjImpl
// ObjTImpl
The idea of redefining abstracts of abstracts goes against the purpose of abstract polymorphism. If the derived types do not intend to implement the inherited abstract member, they should not be inheriting it.
Although the example I gave above would require casting to access any child class-specific members, it would be the proper way to do it in this approach. The runtime needs to know what types it should expect to deal with.
There is always dynamics you could play around with but to be honest I haven't played around with dynamics with generics and inheritance as I suspect I would make my compiler cry, and when it cries, I cry, a little bit deep down inside... lol
It is only possible when you implement the interface explicitly. That's because the return type of a method is not part of its signature - which the compiler checks when overloading. Therefore, otherwise identical methods which only differ in their return type are syntactically not possible.

Generics and Interface issue

Given the following class and interface:
public class Test<T>
{
}
public interface ITesting<T>
{
Test<T> LoadTest();
}
I can add a class with the following:
public class TestManager : ITesting<object>
{
#region ITesting
public Test<object> LoadTest()
{
return new Test<object>();
}
#endregion
}
Which works fine and throws no errors. If I try to replace that class with the following:
public class TestDerived : Test<object>
{
}
public class TestDerivedManager : ITesting<object>
{
#region ITesting
public TestDerived LoadTest()
{
return new TestDerived();
}
#endregion
}
I now get the following error:
Error 'TestDerivedManager' does not implement interface member 'ITesting.LoadTest()'. 'TestDerivedManager.LoadTest()' cannot implement 'ITesting.LoadTest()' because it does not have the matching return type of 'Test'.
But to me it seems like this should work as TestDerived is Test<object>. I'm obviously not understanding something correctly here. Could someone possible point me to details on why this is incorrect? And possibly what I might do to correct it?
The feature you want is called return type covariance. It is a feature of c++ but not of c#, so you'll have to do what the error says.
I recommend you make an explicit interface implementation that calls your public method. That way you get the best of both worlds.
A TestDerived is a Test<object>, yes, but a Test<object> is not a TestDerived.
The contract says that ITesting<object> has a method that can return any Test<object>. Not just one special case (TestDerived).
To make your code work, change it as follows:
public class TestDerivedManager : ITesting<object>
{
public Test<object> LoadTest()
{
return new TestDerived();
}
}
Change the return type of the method back to Test<object> and it should work. The return type is part of the contract when implementing an interface. You can still return the TestDerived since it is a Test<object>.
What you're looking for is called "return type covariance," and unfortunately is not supported by C#. You can't override (or implement) a method with a different return type than the original signature, even if that return type derives from the original return type.
What you can do (which may or may not be a good idea) is implement the interface explicitly and have that call a public method that returns the narrower type you're looking for:
public class TestDerived : Test<object>
{
}
public class TestDerivedManager : ITesting<object>
{
public TestDerived LoadTest()
{
return new TestDerived();
}
Test<object> ITesting<object>.LoadTest()
{
return this.LoadTest();
}
}
That adds an extra layer of complication to your implementation, but it also gives you the public contract you're looking for, along with compatibility with the interface.
Everyone has good technical answer but no one explain why. So I think I will give an illustration about interface.
The general way of interface programming is you should implement the exact method or property described in interface. Let's say that you has interface:
public interface ITesting<T>
{
Test<T> LoadTest();
}
The usage of this interface in your consumer should be like this:
ITesting<object> testingLoader = GetTestingLoader();
Test<object> testingLoader.LoadTest();
If you access the object by using the interface, you don't know the implementation. You only know that the interface ITesting<T> will return Test<T> for the LoadTest() method.
It will come into sense when you see the consumer example above. You (and the compiler) don't (and won't) know that the interface ITesting<object> has a method Test<object> LoadTest() unless you declare it. And what will happen if you try to use an object that is implemented ITesting<object> but has no Test<object> LoadTest() method? It will error won't it?
This is following the LSV principle.

Generics c#.net

In the below code "where T : WsgTypes.RouteRestriction", can I add multiple classes so that T can be of only those few classes types which I am interested of
public static T GetDetails<T>(string code) where T : WsgTypes.RouteRestriction
{
T details;
if (typeof(T) == typeof(WsgTypes.TicketType))
{
details = TicketTypeDetail.GetDetails(code) as T;
}
else if (typeof(T) == typeof(WsgTypes.RouteRestriction))
{
details = RouteRestrictionDetail.GetDetails(code) as T;
}
else
{
throw new NotSupportedException("");
}
return details;
throw new NotImplementedException();
}
It seems to me that this isn't a proper use of generics. It would be better if TicketType and RouteRestriction implemented some IDetailed.
No, generic type constraints can only specify a single base-class.
You can specify multiple interfaces, but this is "all of", not "any of".
What you ask is possible with overloading, but not with generics.
For inheritance you can have a single class with multiple interfaces.
public static T GetDetails<T>(string code) where T : WsgTypes.RouteRestriction, , IComparable
{
}
Instead you can have an interface and have multiple classes implementing it.
public interface IInterface
{}
public class Class1: IInterface
{}
public class Class2: IInterface
{}
public static T GetDetails<T>(string code) where T:IInterface
{
T instance;
// ...
return instance;
}
I'm afraid you can't. The usual way is to provide a common interface that all classes you're interested in implement. The problem is that, inside the generic body, the compiler expects a generic type parameter to be unambigous.
Well, or you could take an object as parameter and cast it at your will. But... no. Don't.
Note that instead of typeof, you could also use the is and as operators.
See this article...
http://msdn.microsoft.com/en-us/library/d5x73970.aspx
... for more information on constaints. You can add multiple constraints, and you can constrain by some interface or by some base class, but not by a list of arbitrary classes.
Here's an example of multiple constraints (from the above):
class Base { }
class Test<T, U>
where U : struct
where T : Base, new() { }
Did you try separating them like this:
public static T GetDetails<T>(string code) where T : WsgTypes.RouteRestriction, NextClass, AnotherClass, AndSoOn
{
...
}

Problem with Covariant return types from an abstract method

I’m trying to wrap up a two day beat down on Abstract methods and return type Covariance, I’ve already posted two similar questions and I am eternally grateful to the community for the info provided, I just need one last push to get to the finish line. Here is what I am trying to do: 2 abstract classes, RecruiterBase and CandidateBase, both have concreate implementations of RecruiterA and CandidateA. RecruiterBase has an abstract method to get all recruited candidates returning IQueryable. My implementation of RecruiterA overrides the GetCandidates() method to return IQueryable.
public abstract class RecruiterBase
{
// Constructors declared here
public abstract IQueryable<CandidateBase> GetCandidates();
}
public abstract class CandidateBase
{
// Constructors declared here
}
and the implementations:
public class CandidateA : CandidateBase
{
// Constructors declared here
}
public class RecruiterA : RecruiterBase
{
// Constructors declared here
// ----HERE IS WHERE I AM BREAKING DOWN----
public override IQueryable<CandidateA> GetCandidates()
{
return from c in db.Candidates
where c.RecruiterId == this.RecruiterId
select new CandidateA
{
CandidateId = c.CandidateId,
CandidateName = c.CandidateName,
RecruiterId = c.RecruiterId
};
}
}
Attempting to complile that throw a compile time error because in my implementation of RecruitreBase the GetCandidates() method returns IQueryable<CandidateA> instead of IQueryable<CandidateBase>.
After not being able to get the suggestions from a previous question (Generic return types from abstract/virtual methods) to work, I did a LOT more reading, and came across the following question in SO
How to return subtype in overridden method of subclass in C#?
Which finally made me realize what I had been searching for was a way to implement Covariance for my return type. I used Marc Gravell's snippet...
abstract class BaseClass
{
public BaseReturnType PolymorphicMethod()
{ return PolymorphicMethodCore();}
protected abstract BaseReturnType PolymorphicMethodCore();
}
class DerivedClass : BaseClass
{
protected override BaseReturnType PolymorphicMethodCore()
{ return PolymorphicMethod(); }
public new DerivedReturnType PolymorphicMethod()
{ return new DerivedReturnType(); }
}
... as the basis for my solution. So now my RecruiterBase and RecruiterA classes look like:
public abstract class RecruiterBase
{
// Constructors declared here
public IQueryable<CandidateBase> GetCandidates()
{
return GetCandidatesCore();
}
public abstract IQueryable<CandidateBase> GetCandidatesCore();
}
and my implementation...
public class RecruiterA : RecruiterBase
{
// Constructors
protected override IQueryable<CandidateBase> GetCandidatesCore()
{
return GetCandidates();
}
public new IQueryable<CandidateA> GetCandidates()
{
return from candidates in db.Candidates
select new CandidateA
{
CandidateId = candidates.CandidateId,
RecruiterId = candidates.RecruiterId
};
}
}
I was hoping that would finally get me what I was looking for but I got a compile time error in the following code because GetCandidates() cannot implicitly convert CandidateA to CandidateBase:
protected override IQueryable<CandidateBase> GetCandidatesCore()
{
return GetCandidates();
}
so I added a cast:
protected override IQueryable<CandidateBase> GetCandidatesCore()
{
return ((IQueryable<CandidateBase>)GetCandidates());
}
Everything then compiles but when I actually call GetCandidates() in my controller it returns IQueryable<CandidateBase> instead of IQueryable<CandidateA>. So I am right back where I started.
If you made it all the way through this and you can help me I'll send you a 12 pack of your favorite beer!
Justin I am a little bit confused why you need to go through all that trouble.
If you abstract method is of return type IQueryable<CandidateBase> then that's what you'll get. I don't see a problem with this, since later on you could still cast it back to CandidateA or CandidateB
So what exactly are you trying to achieve? Maybe I am not understanding you question.
Edit to add:
Justin, what about this?
public abstract class RecruiterBase<T>
{
// Constructors declared here
public abstract IQueryable<CandidateBase> GetCandidates();
}
public abstract class CandidateBase
{
// Constructors declared here
}
public class CandidateA : CandidateBase
{
}
public class RecruiterA : RecruiterBase<RecruiterA>
{
// Constructors declared here
// ----HERE IS WHERE I AM BREAKING DOWN----
public override IQueryable<CandidateBase> GetCandidates()
{
return db.Candidates.Where(cand => cand.RecruiterId == this.RecruiterId)
.Select(x => new CandidateA
{
CandidateId = c.CandidateId,
CandidateName = c.CandidateName,
RecruiterId = c.RecruiterId
})
.Cast<CandidateBase>()
.AsQueryable();
}
}
I think your intentions are good, but the net result is that you're missing the point of polymorphic code and also losing the value.
The purpose of working with objects by their abstract type or by their interfaces is to allow you to work with any concrete implementation, without needing to know any concrete implementation details. I think your belief is that by returning concrete types you are producing higher-quality code, when in fact you're beginning to negate the value of the abstract base class by covering up the abstraction.
A properly built set of derived classes should have only very few needs to be addressed by their concrete types; the abstract class should suffice for working with all implementations and should handle the vast majority of work with those classes--the exceptions should be in the minority.

Categories

Resources