By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,983 Members | 1,110 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,983 IT Pros & Developers. It's quick & easy.

Generics, Collections, Casting

P: n/a
This is a common problem with generics, but I hope someone has found
the best way of solving it.

I have these classes: "Fruit" which is a baseclass, and "Apple" which
is derived. Further I have an "AppleBasket" which is a class that
contains a collection of apples. So, some code:

class Fruit{
}

class Apple : Fruit
{
}

abstract class FruitBasket
{
public void ListFruit()
{
foreach(Fruit fruit in Fruits)
Debug.WriteLine("Hello fruit : "+fruit);
}

abstract ICollection<Fruit> Fruits{ get; }
}

class AppleBasket : FruitBasket
{
// Don't want a <Fruit> collecion here.
private ICollection<Apple> apples;

public ICollection<Fruit> Fruits
{
get{ return apples; } // Can't do this!
}
}
The obvious way is to have a private collection of "Fruit" in the
applebasket, but if I'm doing loads of handling in the Applebasket that
is specific to apples, then I cant do that without casting each fruit
to apple all the time. Not something you want to do *only* because you
have to return the collection as a collection of fruit in one single
property. That would mean that generics really worked to make the code
uglier rather than better.

Also, I cant cast the ICollection<Apple> to ICollection<Fruit> since
they aren't inherited from eachother. Note that the 'AppleBasket' class
in this example isnt supposed to be though of as a collection class or
anything that itself should be generic, like Basket<Apple>, It's just
an unfortunate circumstance of the example...

So how to how to resolve this? any suggestions are welcome...
thanks

Mar 31 '06 #1
Share this Question
Share on Google+
5 Replies


P: n/a
Hi Anders,

Nice Issue, struggled with that one as well. You can use List<Apple>. A
list implements the non-generic Ilist, so you can cast it to that to
loop through the fruit. You cannot cast List<Apple> to List<Fruit>,
because List<Apple> does not derive from List<Fruit>.

--
Ward Bekker
"Asp.Net Discussions for the Professional Developer"
http://www.dotnettaxi.com

"Free .Net 2.0 C# to/from VB.Net Code Converter"
http://www.dotnettaxi.com/Tools/Converter.aspx
Mar 31 '06 #2

P: n/a


an*************@gmail.com wrote:
class AppleBasket : FruitBasket
{
// Don't want a <Fruit> collecion here.
private ICollection<Apple> apples;

public ICollection<Fruit> Fruits
{
get{ return apples; } // Can't do this!
}
} So how to how to resolve this? any suggestions are welcome...
thanks


Use a casting adapter for ICollection<Apple> to ICollection<Fruit> and
return that:

Something along the lines of:

public class AppleBasket: FruitBasket {
public ICollection<Apple> Apples; // any impl of ICollection<Apple>
public ICollection<Fruit> Fruits
{ get { return new UpcasetedCollection<Apple, Fruit>(Apples); } }
...
}

public class UpcastedCollection<T, R> : ICollection<R> where T : R
{
public readonly ICollection<T> Parent;
public UpcastedCollection(ICollection<T> parent)
{ this.Parent = parent; }
public void Add(R r) { Parent.Add((T)r); }
public void Clear() { Parent.Clear(); }
public bool Contains(R r)
{ return r is T && Parent.Contains((T)r); }
public void CopyTo(R[] rs, int index)
{ foreach (T t in Parent) rs[index++] = t; }
public bool Remove(R r) { return r is T && Parent.Remove((T)r); }
public int Count { get { return Parent.Count; } }
public bool IsReadOnly { get { return Parent.IsReadOnly; } }
public IEnumerator<R> GetEnumerator()
{ foreach (T t in Parent) yield return t; }
System.Collections.IEnumerator
System.Collections.IEnumerable.GetEnumerator()
{ return GetEnumerator(); }
}

--
Helge Jensen
mailto:he**********@slog.dk
sip:he**********@slog.dk
-=> Sebastian cover-music: http://ungdomshus.nu <=-
Mar 31 '06 #3

P: n/a
Andreas,

If you use generics for your basked I don't see why you need to use
inheritance. Generics my cause problems, but most of the times the problems
comes from rather incorected design.

If you want to use generics from your basked just do:

class FruitBasket<T>
{
private List<T> fruits = new List<T>();
public void ListFruit()
{
foreach (T fruit in Fruits)
Console.WriteLine("Hello fruit : " + fruit);
}

public ICollection<T> Fruits
{
get
{
return fruits;
}
}

}

When you want to create an apple basked then:

FruitBasket<Apple> appleBasket = new FruitBasket<Apple>()

At the very end this what the generics are all about.

The downside ofcourse is that FruitBasket<Apple> and FruitBasket<Orange>
doesn't have common base class, but if you are going for that you don't need
generics.
--
HTH
Stoitcho Goutsev (100)

<an*************@gmail.com> wrote in message
news:11**********************@j33g2000cwa.googlegr oups.com...
This is a common problem with generics, but I hope someone has found
the best way of solving it.

I have these classes: "Fruit" which is a baseclass, and "Apple" which
is derived. Further I have an "AppleBasket" which is a class that
contains a collection of apples. So, some code:

class Fruit{
}

class Apple : Fruit
{
}

abstract class FruitBasket
{
public void ListFruit()
{
foreach(Fruit fruit in Fruits)
Debug.WriteLine("Hello fruit : "+fruit);
}

abstract ICollection<Fruit> Fruits{ get; }
}

class AppleBasket : FruitBasket
{
// Don't want a <Fruit> collecion here.
private ICollection<Apple> apples;

public ICollection<Fruit> Fruits
{
get{ return apples; } // Can't do this!
}
}
The obvious way is to have a private collection of "Fruit" in the
applebasket, but if I'm doing loads of handling in the Applebasket that
is specific to apples, then I cant do that without casting each fruit
to apple all the time. Not something you want to do *only* because you
have to return the collection as a collection of fruit in one single
property. That would mean that generics really worked to make the code
uglier rather than better.

Also, I cant cast the ICollection<Apple> to ICollection<Fruit> since
they aren't inherited from eachother. Note that the 'AppleBasket' class
in this example isnt supposed to be though of as a collection class or
anything that itself should be generic, like Basket<Apple>, It's just
an unfortunate circumstance of the example...

So how to how to resolve this? any suggestions are welcome...
thanks

Mar 31 '06 #4

P: n/a
I've tested the following successfully:

abstract class FruitBasket<T> where T : Fruit
{
public void ListFruit()
{
}

public abstract ICollection<T> Fruits { get; }
}

class AppleBasket : FruitBasket<Apple>
{
private ICollection<Apple> apples;

public override ICollection<Apple> Fruits
{
get { return apples; }
}
}

--
HTH,

Kevin Spencer
Microsoft MVP
Professional Numbskull

Show me your certification without works,
and I'll show my certification
*by* my works.

<an*************@gmail.com> wrote in message
news:11**********************@j33g2000cwa.googlegr oups.com...
This is a common problem with generics, but I hope someone has found
the best way of solving it.

I have these classes: "Fruit" which is a baseclass, and "Apple" which
is derived. Further I have an "AppleBasket" which is a class that
contains a collection of apples. So, some code:

class Fruit{
}

class Apple : Fruit
{
}

abstract class FruitBasket
{
public void ListFruit()
{
foreach(Fruit fruit in Fruits)
Debug.WriteLine("Hello fruit : "+fruit);
}

abstract ICollection<Fruit> Fruits{ get; }
}

class AppleBasket : FruitBasket
{
// Don't want a <Fruit> collecion here.
private ICollection<Apple> apples;

public ICollection<Fruit> Fruits
{
get{ return apples; } // Can't do this!
}
}
The obvious way is to have a private collection of "Fruit" in the
applebasket, but if I'm doing loads of handling in the Applebasket that
is specific to apples, then I cant do that without casting each fruit
to apple all the time. Not something you want to do *only* because you
have to return the collection as a collection of fruit in one single
property. That would mean that generics really worked to make the code
uglier rather than better.

Also, I cant cast the ICollection<Apple> to ICollection<Fruit> since
they aren't inherited from eachother. Note that the 'AppleBasket' class
in this example isnt supposed to be though of as a collection class or
anything that itself should be generic, like Basket<Apple>, It's just
an unfortunate circumstance of the example...

So how to how to resolve this? any suggestions are welcome...
thanks

Mar 31 '06 #5

P: n/a
<an*************@gmail.com> a écrit dans le message de news:
11**********************@j33g2000cwa.googlegroups. com...

| I have these classes: "Fruit" which is a baseclass, and "Apple" which
| is derived. Further I have an "AppleBasket" which is a class that
| contains a collection of apples.

| The obvious way is to have a private collection of "Fruit" in the
| applebasket, but if I'm doing loads of handling in the Applebasket that
| is specific to apples, then I cant do that without casting each fruit
| to apple all the time. Not something you want to do *only* because you
| have to return the collection as a collection of fruit in one single
| property. That would mean that generics really worked to make the code
| uglier rather than better.
|
| Also, I cant cast the ICollection<Apple> to ICollection<Fruit> since
| they aren't inherited from eachother. Note that the 'AppleBasket' class
| in this example isnt supposed to be though of as a collection class or
| anything that itself should be generic, like Basket<Apple>, It's just
| an unfortunate circumstance of the example...
|
| So how to how to resolve this? any suggestions are welcome...

Try the following :

class Fruit
{
}

class Apple : Fruit
{
}

abstract class Basket<fruitT> where fruitT : Fruit
{
public void ListFruit()
{
foreach (fruitT fruit in fruits)
Console.WriteLine("Hello fruit : " + fruit);
}

private IList<fruitT> fruits = new List<fruitT>();

public IList<fruitT> Fruits
{
get { return fruits; }
}
}

class AppleBasket : Basket<Apple>
{

}

Joanna

--
Joanna Carter [TeamB]
Consultant Software Engineer
Apr 1 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.