![]() |
![]() |
|
|||||||
| Register | Forum Rules | Getting Started! - Guide | Blog | Videos | Gallery | Members List | Social Groups | Mark Forums Read |
![]() |
|
|
LinkBack | Thread Tools | Display Modes |
|
|
#1 |
|
Guest
Posts: n/a
|
Suggestions? Returning subclass instances from parent class methods
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? |
|
|
|
#2 |
|
Guest
Posts: n/a
|
Re: Suggestions? Returning subclass instances from parent class methods
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). -- Adam Clauss "Niels Ull" <nielsull@hotmail.com> wrote in message news:97b66c3d363bc8c9debe96df98c8@msnews.microsoft .com... > 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? > > |
|
|
|
#3 |
|
Guest
Posts: n/a
|
Re: Suggestions? Returning subclass instances from parent class methods
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. -- Adam Clauss "Adam Clauss" <cabadam@gmail.com> wrote in message news:4716e070$0$11090$4c368faf@roadrunner.com... > 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). > > -- > Adam Clauss > > > "Niels Ull" <nielsull@hotmail.com> wrote in message > news:97b66c3d363bc8c9debe96df98c8@msnews.microsoft .com... >> 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? >> >> > > |
|
|
|
#4 |
|
Guest
Posts: n/a
|
Re: Suggestions? Returning subclass instances from parent class methods
Thanks - that trick looks like just what I needed.
|
|
![]() |
| Thread Tools | |
| Display Modes | |
|
|
< Home - Windows Help - MS Office Help - Hardware Support >
| New To Site? | Need Help? |