Cannot use LINQ methods on IEnumerable base class from derived class - c#

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

Related

Restrict passing instances of derived classes as method parameters

Here's the situation. I have a class and a derived class
public class MyClass
{ }
public class MyDerivedClass : MyClass
{ }
And also I have a method (in an external class) which takes an instance of MyClass as a parameter:
public class AnotherClass {
public void DoSomething(MyClass myClass)
{ }
}
How can I restrict DoSomething method to accept instances of MyClass only, but not instances of MyDerivedClass?
If that's what you want then you would need to check in code yourself that if it is a Derived type through Exception to tell the calling code that Derived type objects are not allowed for this method:
public class AnotherClass {
public void DoSomething(MyClass myClass)
{
if(myClass.GetType() != typeof(MyClass))
{
throw new Exception("Derived objects not allowed");
}
}
}
What are you trying to do here is more related to an Invariance problem that is pretty common on all programming languages.
Means that you can use only the type originally specified; so an
invariant generic type parameter is neither covariant nor
contravariant. You cannot assign an instance of IEnumerable
(IEnumerable) to a variable of type
IEnumerable or vice versa.
Here is the reference for you https://msdn.microsoft.com/en-us/library/dd799517(v=vs.110).aspx
My advice, try to change the implementation and put all the methods into an interface, that should be more clear
class Root: Interface
{
...implementation of your common methods
}
class Derived: Interface
{
...implementation of your common methods
//this should just
public void DoSomething(MyClass myClass)
}
If you don't want to use the above approach then use the "as" operator to treat the parameter that you are passing as MyRootClass, var a = parameter as MyRootClass. If a is null then you are not passing the correct value to the method, or check for the type directly.
If would recommend that you read this topics:
http://amapplease.blogspot.com/2009/04/invariance-covariance-contravariance.html
https://stackoverflow.com/a/13107168/819153
https://blogs.msdn.microsoft.com/ericlippert/2009/03/19/representation-and-identity/
Hope this helps

Implement copy/deepcopy on multiple base classes

not sure if this maybe is a codeReview post but here we go:
My goal is to re-implement the way objects are copied within our application. We have multiple base classes:
CoreList<T> // for all list classes
BasicReference // for all reference classes
CoreObject // for all "normal" domain objects
All classes inherit from these base classes. Right now the copy method is implemented on the CoreObject class and will go through the object tree via reflection, looking at each property type and select the correct way to copy the type and finally returning always CoreObject.
There are some problems which I don't like about that approach, which is why I would like to change it:
After copying an domain object you always have to cast it "back" to the original type, for example: Animal = animal.Copy() as Animal;
All logic to copy each type is within the CoreObject class even though it should not know about other base classes.
So my first attempt was to introduce a interface:
public interface IObjectCopy<out T>
{
T Copy();
}
Which then should be implemented on all base classes. Then every class is responsible for the way it is copied. For example (pseudo code):
public class CoreObject : IObjectCopy<CoreObject>
{
public virtual GerCoreObject Copy()
{
foreach (var prop in properties)
{
if (prop.IsNoSimpleType)
{
(prop as IObjectCopy).Copy()
}
}
}
That solves the copy-responsibility problem, in addition inherited classes can take care of the copy logic themselves.
Unfortunately that does not solve the return type, I still have to cast it to the correct type. I did not think of a better solution to solve this. Any ideas?
This problem could be solved in OO using covariant return types. Unfortunately C# does not support covariant return types like Java and C++, requiring it to always break type safety.
Without breaking type safety (casting) in C# this is unfortunately not possible.
Here are two possible options:
//explicit interface implementation
public class Animal : CoreObject, IObjectCopy<Animal>
{
Animal IObjectCopy<Animal>.Copy()
{
return (Animal) base.Copy();
}
}
//does not require an explicit cast
IObjectCopy<Animal> animalCopy = myAnimal;
Animal copiedAnimal = animalCopy.Copy();
//second option: shadow the original method and cast inside the object
public class Animal : CoreObject, IObjectCopy<Animal>
{
public new Animal Copy()
{
return (Animal) base.Copy();
}
}
Animal copy = myAnimal.Copy();
Another option using bounded quantification:
public class CoreObject : IObjectCopy<CoreObject>
{
public CoreObject Copy()
{
return Copy<CoreObject>();
}
protected T Copy<T>()
where T : CoreObject, new()
{
T t = new T();
//implement copy logic:
return t;
}
}
public class Animal : CoreObject, IObjectCopy<Animal>
{
public new Animal Copy()
{
return Copy<Animal>();
}
}
If I understood it correctly, you need Curiously recurring template pattern
public class BaseClass<T> where T : BaseClass<T>
{
public virtual T Clone()
{
// Perform cloning with reflection.
return clone as T;
}
}
Then you just define your class as:
public class EndObject : BaseClass<EndObject>
{
}
EndObject e;
e.Clone() // Will return EndObject type

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.

Implementing C# Dictionary results in error: Does not have matching return type

I am trying to understand how C# implements the Dictionary. It seems to me that Dictionary is supposed to inherit from IEnumerable which requires the method implementation for:
IEnumerable GetEnumerator()
However, the C# Dictionary instead implements:
Dictionary<T>.Enumerator GetEnumerator()
Where Enumerator is a nested struct which inherits from IEnumerator.
I have created an example of this relationship:
public interface IFoo
{
IFoo GetFoo();
}
public abstract class Foo : IFoo
{
public abstract FooInternal GetFoo();
public struct FooInternal : IFoo
{
public IFoo GetFoo()
{
return null;
}
}
}
However, this doesn't compile, resulting in the following error:
Error 2 'Foo' does not implement interface member 'IFoo.GetFoo()'. 'Foo.GetFoo()' cannot implement 'IFoo.GetFoo()' because it does not have the matching return type of 'CodeGenerator.UnitTests.IFoo'. Foo.cs 14
Any thoughts on what I might be doing wrong here? How does C# implement the Dictionary? How would one make the example code compile similarly to the C# Dictionary?
You are missing an explicit interface implementation:
public abstract class Foo : IFoo
{
public abstract FooInternal GetFoo();
// start here
IFoo IFoo.GetFoo()
{
return GetFoo();
}
// end here
public struct FooInternal : IFoo
{
public IFoo GetFoo()
{
return null;
}
}
}
You are confusing two distinct interfaces, namely IEnumerable and IEnumerator.
The outer class, the dictionary class, implements IEnumerable. This involves that the outer class has a method GetEnumerator. This method returns an instance of the nested (inner) struct.
The inner struct implements IEnumerator. To implement IEnumerator you must have a MoveNext method and a Current property.
Besides, there's the issue of explicit interface implementation which is mentioned also by Andrey Shchekin's answer. This code is legal and similar to Dictionary<,>:
public interface IFoo // corresponds to IEnumerable
{
IBar GetBar();
}
public interface IBar // corresponds to IEnumerator
{
}
public class Foo : IFoo
{
// public method that has BarInternal as return type
public BarInternal GetBar()
{
return new BarInternal();
}
// explicit interface implementation which calls the public method above
IBar IFoo.GetBar()
{
return GetBar();
}
public struct BarInternal : IBar
{
}
}
It would also be possible to implement the IFoo "directly" (not explicitly) by a public method, but then the declared return type must match:
public class Foo : IFoo
{
// public method that directly implements the interface
public IBar GetBar()
{
return new BarInternal();
}
public struct BarInternal : IBar
{
}
}
The reason why Dictionary<,> isn't written in this simpler way, is that you get boxing of the nested struct, I guess.
Note that when you foreach through a Dictionary<,>, the C# compiler first searches for a public non-generic parameterless instance method with the exact name GetEnumerator. If such a method is found, it is used, and the compiler doesn't care about IEnumerable. Therefore, with a Dictionary<,>, the slightly more optimal public method which does not implement the interface, is used during foreach.
Explicit interface implementations are documented on MSDN. See Dictionary<TKey, TValue>.IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator (generic) and Dictionary<TKey, TValue>.IEnumerable.GetEnumerator (non-generic).

C# covariance and inheritance

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.

Categories

Resources