Generics

  • Thread starter Thread starter Robert
  • Start date Start date
R

Robert

Hi,

I have a generic List that holds a type that must inheret from a base
type and implement a interface.
Can I use the generic list without nowing the derived type?
Here is some code to explain the situation (i hope):

namespace Nevermind
{
public abstract class BaseCar
{
public void Start() { }
}
public interface IDoSomething
{
void DoIt();
}

public class CarList<Tcar> : List<Tcar> where Tcar : BaseCar,
IDoSomething
{
}

public class BigCar : BaseCar, IDoSomething
{
public void DoIt()
{ }
}
public class SmallCar : BaseCar, IDoSomething
{
public void DoIt()
{ }
}


public class BuildCars
{
//I want to hold a list with cars, can be smallcars or BigCars
//but the compiler doesn't like this:
CarList<Tcar> cars;
//he doesn't like this either:
CarList<BaseCar> cars;
}
}

Tanx in advance!
 
Hi Rober,
//I want to hold a list with cars, can be smallcars or BigCars
//but the compiler doesn't like this:
CarList<Tcar> cars;
//he doesn't like this either:
CarList<BaseCar> cars;

Suppying a Type name in the <> of a generic Type, when creating an instance,
tells the compiler which Type will be used in place of the TCar parameter
throughout the class.

CarList<Tcar> doesn't work because Tcar isn't an actual Type, it's the
generic Type parameter your are supposed to be replacing with an actual
Type.

CarList<BaseCar> doesn't work because BaseCar doesn't implement
IDoSomething, as per your instructions to the compiler in the following
line:
where Tcar : BaseCar, IDoSomething

You could have BaseCar implement IDoSomething to satisfy the where criteria.
It makes more sense anyway, from an architectural POV, if all of your
derived car classes are going to implement IDoSomething and derive from
BaseCar anyway.

Another way to successfully use CarList<BaseCar> = new CarList<BaseCar>() is
to remove the IDoSomething interface criteria from the where statement of
the CarList class.

You could also remove the BaseCar criteria from the where statement of the
CarList class and use CarList<IDoSomething> = new CarList<IDoSomething>().

HTH
 
Thanks for the replay Dave,
The problem is that I can't change the "car" classes because they are
from an external component. There probably isn't a solution for this
other than removing the interface from the where clause and cast to the
interface when needed.
grt R.


Dave Sexton schreef:
 
If you have a collection that holds BaseCar objects, you can add both
BigCar and SmallCar objects to the list:

public class CarList : List<BaseCar>
{
}

CarList list = new CarList();
list.Add(new BigCar());
list.Add(new SmallCar());

Unless you need to add members to the collection, you could just do:

List<BaseCar> list = new List<BaseCar>;
list.Add(new BigCar());
list.Add(new SmallCar());


Since you don't have access to the BaseCar class, you cannot add the
requirement for sub-classes to implement an interface.

What you might want to consider is to make an abstract class that
inherits BaseCar and implements IDoSomething and subclass off of that.
Something like:

public interface IDoSomething
{
void SomeMethod(int x);
string SomeProperty { get; set;}
}

public abstract MyBaseCar : BaseCar, IDoSomething
{
abstract public void SomeMethod(int x);
abstract public string SomeProperty { get; set; }
}

public class BigCar : MyBaseCar
{
public override void SomeMethod(int x)
{
// do something
}

public override string SomeProperty
{
get
{
return "Something";
}
set
{
// set something
}
}
}

public class SmallCar : MyBaseCar
{
public override void SomeMethod(int x)
{
// do something
}

public override string SomeProperty
{
get
{
return "Something";
}
set
{
// set something
}
}
}

public class CarList : List<MyBaseCar>
{
}

CarList list = new CarList();

list.Add(new BigCar());
list.Add(new SmallCar());

The subclasses of the abstract class are required to implement any
abstract member. By implementing the interface members as abstract,
you pass on the implementation requirement to the subclasses.



What you did was confuse creating your own generic class with
inheriting an existing generic class. You didn't need the <Tcar> in
your class type (the public class CarList<Tcar>) unless you were
creating a new generic type. Or, maybe you actually wanted to and then
you wouldn't inherit from List<Tcar> - you would just implement
ICollection<Tcar>. Like:

public class CarList<Tcar>
: where Tcar : BaseCar
: ICollection<Tcar>, IDoSomething
{
// methods and properties to implement ICollection<Tcar> and
IDoSomething
}

which is a LOT more work than needed if you just need a list.
 
Back
Top