471,306 Members | 1,233 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,306 software developers and data experts.

Generics, IEnumerable and Polymorphism

It looks to me that in using that in creating generic IEnumerables, you
lose polymorphic capabilities.

Consider this pseudo code:

abstract class BaseClass;

class DerivedClassSpecialFunction1 : BaseClass
class DerivedClassSpecialFunction2 : BaseClass

class Function1ImplementationA : DerivedClassSpecialFunction1
class Function1ImplementationB : DerivedClassSpecialFunction1
List<BaseClass> mylist = new List<BaseClass>

// assume the above list gets populated with a mix of the above classes

foreach (BaseClass item in mylist)
{
DerivedClassSpecialFunction1 derivedItem = item as
DerivedClassSpecialFunction1;

if (derivedItem != null)
{
derivedItem.CallSpecialFunction();
}
}

This allows me to iterate through a list of objects all subclassed from
the same absrtact class and then, for only specific types, call some
function. The function called is the correct function for the instance
type.

I then tried to create an IEnumerator method to try to clean this up a
bit (hoping to avoid testing for the right type everytime (and also
checking for null).

My iterator looked something like this:

public IEnumerator<DerivedClassSpecialFunction1>
GetSpecialFunction1ClassesOnly()
{
foreach (BaseClass item in mylist)
{
if (item is DerivedClassSpecialFunction1) yield return item;
}
}
So, later if I use this enumerator in a foreach call like this:

foreach (DerivedClassSpecialFunction1 item in
GetSpecialFunctionClassesOnly())
{
item.CallSpecialFunction();
}

This does not work correctly. Instead of calling the
Function1ImplementationA version of CallSpecialFunction(), it always
uses the DerivedClassSpecialFunction version.

Is there a way to do what I want and still use custom enumerators? I
want to selectively filter on type, but retain the polymorphic
abilities of subclasses from that type.

Thanks!

Mike

Dec 20 '05 #1
4 1947
Mike,
This does not work correctly. Instead of calling the
Function1ImplementationA version of CallSpecialFunction(), it always
uses the DerivedClassSpecialFunction version.


That's not what I'm seeing. Below is a cleaned up version of your code
that actually compiles. The output is

DerivedClassSpecialFunction1
Function1ImplementationA
Function1ImplementationB

which is what I expect and seems perfectly polymorphic. If you get
something else please post your complete code. Here's mine:

using System;
using System.Collections.Generic;

abstract class BaseClass
{
public virtual void CallSpecialFunction() {
Console.WriteLine("BaseClass"); }
}

class DerivedClassSpecialFunction1 : BaseClass
{
public override void CallSpecialFunction() {
Console.WriteLine("DerivedClassSpecialFunction1"); }
}

class DerivedClassSpecialFunction2 : BaseClass
{
public override void CallSpecialFunction() {
Console.WriteLine("DerivedClassSpecialFunction2"); }
}

class Function1ImplementationA : DerivedClassSpecialFunction1
{
public override void CallSpecialFunction() {
Console.WriteLine("Function1ImplementationA"); }
}

class Function1ImplementationB : DerivedClassSpecialFunction1
{
public override void CallSpecialFunction() {
Console.WriteLine("Function1ImplementationB"); }
}

class Test
{
static List<BaseClass> mylist = new List<BaseClass>();

public static IEnumerable<DerivedClassSpecialFunction1>
GetSpecialFunction1ClassesOnly()
{
foreach (BaseClass item in mylist)
{
DerivedClassSpecialFunction1 dcsf1 = item as
DerivedClassSpecialFunction1;
if (dcsf1 != null) yield return dcsf1;
}
}

static void Main()
{

mylist.Add(new DerivedClassSpecialFunction1());
mylist.Add(new DerivedClassSpecialFunction2());
mylist.Add(new Function1ImplementationA());
mylist.Add(new Function1ImplementationB());

foreach (DerivedClassSpecialFunction1 item in
GetSpecialFunction1ClassesOnly())
{
item.CallSpecialFunction();
}

}
}
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Dec 20 '05 #2
"Mike" <mi*********@mbna.com> a écrit dans le message de news:
11*********************@g14g2000cwa.googlegroups.c om...

| So, later if I use this enumerator in a foreach call like this:
|
| foreach (DerivedClassSpecialFunction1 item in
| GetSpecialFunctionClassesOnly())
| {
| item.CallSpecialFunction();
| }
|
| This does not work correctly. Instead of calling the
| Function1ImplementationA version of CallSpecialFunction(), it always
| uses the DerivedClassSpecialFunction version.

I used the following code :

public abstract class BaseClass
{
}

public class DerivedClassSpecialFunction1 : BaseClass
{
public virtual void CallSpecialFunction()
{
}
}

public class DerivedClassSpecialFunction2 : BaseClass
{
}

public class Function1ImplementationA : DerivedClassSpecialFunction1
{
public override void CallSpecialFunction()
{
}
}

public class Function1ImplementationB : DerivedClassSpecialFunction1
{
public override void CallSpecialFunction()
{
}
}

private List<BaseClass> mylist = new List<BaseClass>();

public IEnumerator<DerivedClassSpecialFunction1>
GetSpecialFunction1ClassesOnly()
{
foreach (BaseClass item in mylist)
{
if (item is DerivedClassSpecialFunction1)
yield return (DerivedClassSpecialFunction1) item;
}
}
Then I use dthe following test code :

private void button1_Click(object sender, EventArgs args)
{
mylist.Add(new Function1ImplementationA());
mylist.Add(new DerivedClassSpecialFunction2());
mylist.Add(new Function1ImplementationB());
mylist.Add(new Function1ImplementationA());

IEnumerator<DerivedClassSpecialFunction1> iter =
GetSpecialFunction1ClassesOnly();

while (iter.MoveNext())
iter.Current.CallSpecialFunction();

This then works perfectly calling the correct overriden method only on those
items that are derived from DerivedClassSpecialFunction1.

If I change the test code to the following :

foreach (DerivedClassSpecialFunction1 item in
GetSpecialFunction1ClassesOnly())
{
item.CallSpecialFunction();
}

.... then this doesn't even compile ! You can't use foreach on an
IEnumerator, only on an IEnumerable or an object that has a GetEnumerator()
method.

Joanna

--
Joanna Carter [TeamB]
Consultant Software Engineer
Dec 20 '05 #3
"Joanna Carter [TeamB]" <jo****@not.for.spam> a écrit dans le message de
news: Ok****************@TK2MSFTNGP09.phx.gbl...

| If I change the test code to the following :
|
| foreach (DerivedClassSpecialFunction1 item in
| GetSpecialFunction1ClassesOnly())
| {
| item.CallSpecialFunction();
| }
|
| ... then this doesn't even compile ! You can't use foreach on an
| IEnumerator, only on an IEnumerable or an object that has a
GetEnumerator()
| method.

My bad, I forgot to declare the GetSpecialFinction1ClassesOnly method as
static.

Like Mattias, Now I find this code works perfectly as expected.

Did you declare your CallSpecialFunction() as virtual and override where
necessary ??

Joanna

--
Joanna Carter [TeamB]
Consultant Software Engineer
Dec 20 '05 #4
Thanks Mattias and Joanna,

I hate to say it, but turns out the problem was hidden elsewhere and
this so-called "loss of polymorphism" was the false symptom. I did not
trace through the code properly and mis-diagnosed the problem.

Turns out my IEnumerable code was all in perfect working order. This
is a relief as I had fooled myself into thinking a core OO concept had
been trashed by M$... but alas, it is just my ego that is trashed! ;-)

The system I am working on is complex (aren't they all, right?). There
is a method that looks for a context object that is transitory. If it
finds a current context, it will return an IEnumerable from this
context, otherwise it will build it's own empty one. Hard to explain
all the details on why, but the context was being queried at a time
when it could not have been set. This was my mistake. I assumed it
would be there at a time that it could not be. As a result, downstream
in the code, the symptom appeared to be a loss of polymorphism. Once I
traced through the code patiently and properly, it was plain as day for
me.

Thanks so much for taking the time to respond to my query. It was your
quick responses that got me to stop thinking it was a polymorphism
issue and to start looking for the real problem!

What a great community!

Thanks!

Mike

Dec 21 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by Kamen Yotov | last post: by
13 posts views Thread by Sherif ElMetainy | last post: by
2 posts views Thread by Marc | last post: by
2 posts views Thread by rajivpopat | last post: by
19 posts views Thread by Fernando Cacciola | last post: by
3 posts views Thread by Wiktor Zychla [C# MVP] | last post: by
10 posts views Thread by =?Utf-8?B?S29ucmFkIFJ1ZG9scGg=?= | last post: by
4 posts views Thread by CSharper | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.