|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Casting IEnumerable<T> to IEnumerable<V>public class Friends: ReadOnlyCollection<Friend> {} where Friend implements IPerson: public class Friend:IPerson {} My question: is there a neat+lean way to implement IEnumerable<Person> in the collection class?: public class Friends: ReadOnlyCollection<Friend>, IEnumerable<Person> { public new IEnumerator<Person> GetEnumerator() { // ******* CAST DOES NOT WORK ********** return (IEnumerator < IVSelItem >) base.GetEnumerator(); } } Any suggestions? Thanks in advance. "Daniel" <dfi***@gmail.com> wrote: Neat and lean? Not totally. Covariance is required here, and it isn't> Suppose a collection class defined as: > > public class Friends: ReadOnlyCollection<Friend> {} > > where Friend implements IPerson: > > public class Friend:IPerson {} > > My question: is there a neat+lean way to implement IEnumerable<Person> > in the collection class?: supported by C#. The best you can do is this (which is neat, but not 100% lean): ---8<--- static IEnumerable<T> Cast<T>(IEnumerable source) { foreach (object item in source) yield return (T) item; } --->8--- -- Barry "Daniel" <dfi***@gmail.com> a écrit dans le message de news: 1151668651.537391.11***@d56g2000cwd.googlegroups.com...Show quote | Suppose a collection class defined as: Does this help ?| | public class Friends: ReadOnlyCollection<Friend> {} | | where Friend implements IPerson: | | public class Friend:IPerson {} | | My question: is there a neat+lean way to implement IEnumerable<Person> | in the collection class?: | | public class Friends: ReadOnlyCollection<Friend>, IEnumerable<Person> | { | | public new IEnumerator<Person> GetEnumerator() | { | // ******* CAST DOES NOT WORK ********** | return (IEnumerator < IVSelItem >) base.GetEnumerator(); | } | } public interface IPerson { } public class Friend : IPerson { } public class Friends : List<Friend>, IEnumerable<IPerson> { public new IEnumerator<IPerson> GetEnumerator() { foreach (Friend friend in (this as IEnumerable<Friend>)) yield return friend as IPerson; } } ....used like this : { Friends friends = new Friends(); friends.Add(new Friend()); friends.Add(new Friend()); friends.Add(new Friend()); ReadOnlyCollection<Friend> roFriends = new ReadOnlyCollection<friends>; foreach (IPerson person in roFriends) ... ; } ....although this would also work with the same code : { Friends friends = new List<Friend>(); friends.Add(new Friend()); friends.Add(new Friend()); friends.Add(new Friend()); ReadOnlyCollection<Friend> roFriends = new ReadOnlyCollection<friends>; foreach (IPerson person in roFriends) ... ; } I think you are making things overly complicated :-) Joanna -- Joanna Carter [TeamB] Consultant Software Engineer Thanks !
It works ! but I think yielding the elements will be more expensive than using System.Collections.IEnumerator and casting to IPerson, from a performance standpoint. Joanna: yes, it seems overcomplicated the way I presented it, but maybe is because I reduced the complexity just to show the issue... Let me explain more: I have several collections like Friends: Men (collection of Man:IPerson), Women (collection of Woman:IPerson), Artists (collection of Artist:IPerson), and so on; all of them derive from ReadOnlyCollection<T> Now I need these collections to show certain behavior and present themselves thorough an interfase named IGroupOfPeople, like: interfase IGroupOfPeople: IEnumerable<IPerson> { void SayHi(); int AverageHeight {get;} } now, the collections will implement the interfase IGroupOfPeople, and therefore they must provide the GetEnumerator<IPerson>. Maybe is better to modify the interfase to : interfase IGroupOfPeople: System.Collections.IEnumerable { void SayHi(); int AverageHeight {get;} } And let the users of the collection the casting from System.Object to IPerson. I hope I could explain myself. Thanks Daniel "Daniel" <dfi***@gmail.com> a écrit dans le message de news: 1151696433.820867.289***@b68g2000cwa.googlegroups.com...| Thanks ! As I showed in the second example, you don't even need to write a separate | | It works ! but I think yielding the elements will be more expensive | than using System.Collections.IEnumerator and casting to IPerson, from | a performance standpoint. enumerator, you can just do a foreach on a List<Friend> asking for the element as IPerson and it will work. | I have several collections like Friends: Men (collection of Why are you deriving from ReadOnlyCollection<T> ? It is only a read-only | Man:IPerson), Women (collection of Woman:IPerson), Artists (collection | of Artist:IPerson), and so on; all of them derive from | ReadOnlyCollection<T> wrapper class that has to take a list that implements IList<T>. Unless you are planning on adding extra list functionality, there really is no need to derive from generic list classes; all you need is usually in the class as it stands. | Now I need these collections to show certain behavior and present This is bad design. You should keep the IEnumerable behaviour separate from | themselves thorough an interfase named IGroupOfPeople, like: | | interfase IGroupOfPeople: IEnumerable<IPerson> | { | void SayHi(); | int AverageHeight {get;} | } | | now, the collections will implement the interfase IGroupOfPeople, and | therefore they must provide the GetEnumerator<IPerson>. any "group" behaviour. | Maybe is better to modify the interfase to : Not a good idea; this is just what generic classes seek to eliminate.| | interfase IGroupOfPeople: System.Collections.IEnumerable | { | void SayHi(); | int AverageHeight {get;} | } | | And let the users of the collection the casting from System.Object to | IPerson. Joanna -- Joanna Carter [TeamB] Consultant Software Engineer > Deriving from ReadOnlyCollection was based on the prospective use of> | I have several collections like Friends: Men (collection of > | Man:IPerson), Women (collection of Woman:IPerson), Artists (collection > | of Artist:IPerson), and so on; all of them derive from > | ReadOnlyCollection<T> > > > Why are you deriving from ReadOnlyCollection<T> ? It is only a read-only > wrapper class that has to take a list that implements IList<T>. Unless you > are planning on adding extra list functionality, there really is no need to > derive from generic list classes; all you need is usually in the class as it > stands. > the collections: they populate themselves (from the data tier) and should be ReadOnly fpr their consumers, that's the reason for using the wrapper instead of IList<T> Show quote > | Now I need these collections to show certain behavior and present I don't understand where is the "badness": consumers accessing objects> | themselves thorough an interfase named IGroupOfPeople, like: > | > | interfase IGroupOfPeople: IEnumerable<IPerson> > | { > | void SayHi(); > | int AverageHeight {get;} > | } > | > | now, the collections will implement the interfase IGroupOfPeople, and > | therefore they must provide the GetEnumerator<IPerson>. > > This is bad design. You should keep the IEnumerable behaviour separate from > any "group" behaviour. > that implement IGroupOfPeople will be only interested in enumerating its members (IPersons), I thought that the cleanest way is to just expose the IEnumerable<IPerson> interfase, is there a better way? Daniel |
|||||||||||||||||||||||