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 / .NET Framework / New Users / July 2006

Tip: Looking for answers? Try searching our database.

Casting IEnumerable<T> to IEnumerable<V>

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Daniel - 30 Jun 2006 12:57 GMT
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?:

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.
Barry Kelly - 30 Jun 2006 13:54 GMT
> Suppose a collection class defined as:
>
[quoted text clipped - 6 lines]
> My question: is there a neat+lean way to implement IEnumerable<Person>
> in the collection class?:

Neat and lean? Not totally. Covariance is required here, and it isn't
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

Signature

http://barrkel.blogspot.com/

Joanna Carter [TeamB] - 30 Jun 2006 18:57 GMT
| Suppose a collection class defined as:
|
[quoted text clipped - 16 lines]
|        }
| }

Does this help ?

 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

Signature

Joanna Carter [TeamB]
Consultant Software Engineer

Daniel - 30 Jun 2006 20:40 GMT
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
Joanna Carter [TeamB] - 30 Jun 2006 22:10 GMT
| 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.

As I showed in the second example, you don't even need to write  a separate
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
| 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.

| Now I need these collections to show certain behavior and present
| themselves thorough an interfase named IGroupOfPeople, like:
[quoted text clipped - 7 lines]
| 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.

| Maybe is better to modify the interfase to :
|
[quoted text clipped - 6 lines]
| And let the users of the collection the casting from System.Object to
| IPerson.

Not a good idea; this is just what generic classes seek to eliminate.

Joanna

Signature

Joanna Carter [TeamB]
Consultant Software Engineer

Daniel - 01 Jul 2006 21:38 GMT
> | I have several collections like Friends: Men (collection of
> | Man:IPerson), Women (collection of Woman:IPerson), Artists (collection
[quoted text clipped - 6 lines]
> derive from generic list classes; all you need is usually in the class as it
> stands.

Deriving from ReadOnlyCollection was based on the prospective use of
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>

> | Now I need these collections to show certain behavior and present
> | themselves thorough an interfase named IGroupOfPeople, like:
[quoted text clipped - 10 lines]
> This is bad design. You should keep the IEnumerable behaviour separate from
> any "group" behaviour.

I don't understand where is the "badness": consumers accessing objects
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

Rate this thread:







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.