Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / October 2007

Tip: Looking for answers? Try searching our database.

Suggestions? Returning subclass instances from parent class methods

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Niels Ull - 17 Oct 2007 09:21 GMT
Hi!

I have a generic abstract base class MyCollection<T> which represents a collection
of T's with some common utility methods.
I then have a number of non-generic subclasses, e.g.

class FooCollection : MyCollection<Foo>
{   /* utility methods only for foo collections */ }

class BarCollection : MyCollection<Bar>
{   /* utility methods only for Bar collections */ }

Now, I'd like to provide a subset method in MyCollection - e.g. for getting
the first 10 items
(In real life selecting the subset is more complex and based on the structure
of MyCollection as well as properties of the T base type)

FooCollection allFoos = ...
FooCollection tenFoos = allFoos.GetSubset(10);

But I'd like to return a FooCollection - not a MyCollection<Foo>. The best
I have been able to come up is this method in MyCollection:

DERIVEDCOLLECTION GetSubset<DERIVEDCOLLECTION>(int count) where DERIVEDCOLLECTION:
MyCollection<T>, new()
{
 DERIVEDCOLLECTION result = new DERIVEDCOLLECTION();
 for(int i = 0; i < count; i++) // example logic only!
    result.Add(this[i]);
 return result;
}

This is not very elegant, since it requires the user to specify the target
class:
FooCollection tenFoos = allFoos.GetSubset<FooCollection>(10);

An alternative would be to return an IEnumerable<T>, but that would require
the user to write

FooCollection allFoos = ...
FooCollection tenFoos = new FooCollection();
tenFoos.AddAll(allFoos.GetSubset(10))

Or, finally, I could implement new GetSubset in all derived collections -
but since there are a number of such functions, that's not too useful either.

Does anybody have any suggestions?
Adam Clauss - 18 Oct 2007 05:26 GMT
One possibility, add a second type to the generic parameters:

class FooCollection : MyCollection<Foo, FooCollection>
{}

where MyCollection is now something like:

class MyCollection<T,S> where S : new()
{
   public S GetSubset(int count)
   {
       S newCollection = new S();
       for (int i = 0; i < count; i++)
       {
           newCollection.Add(this[i]);
       }
       return newCollection;
   }
}

This would then simplify the callers syntax to simply:

FooCollection tenFoos = allFoos.GetSubset(10);

Which was what you wanted correct?

This comes with an assumption: that each of your subclasses has a default
constructor (presumably to create an empty collection).

Signature

Adam Clauss

> Hi!
>
[quoted text clipped - 43 lines]
>
> Does anybody have any suggestions?
Adam Clauss - 18 Oct 2007 05:40 GMT
Realized I forgot one more thing before that will work.
>        S newCollection = new S();
>            newCollection.Add(this[i]);

In order to call newCollection.Add(), we need the compiler to know that S
actually derives from MyCollection, more specifically MyCollection of the
same type (T).  So change the MyCollection definition to:
class MyCollection<T,S> where S : MyCollection<T,S>, new()

It looks a bit redundant, but it ties all the appropriate things together to
let the compiler know that anything of type S is effectively the same as
itself.

Signature

Adam Clauss

> One possibility, add a second type to the generic parameters:
>
[quoted text clipped - 73 lines]
>>
>> Does anybody have any suggestions?
Niels Ull - 19 Oct 2007 12:53 GMT
Thanks - that trick looks like just what I needed.

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.