About generics

T

Tony Johansson

Hello!

Assume you have this generic Dictionary class with key, value pair the first
part is the key and the second part is the value part.
The key value is a string and the value part is the Car.
Dictionary<string, Car> directory = new Dictionary<string, Car>();
Now to my question assume that you have a derived class called BMW below the
base class Car.

Is it then legal to use BMW instead of Car because BMW is a Car or are you
obliged to use exactly
the same type (here Car) as the one you used when you instansiated the
object directory of type Dictionary.

I assume that this is the main point of using generics to use exactly the
same type because if this was not the case you could all the same use the
general class.

class Car
{
....
}

class BMW : Car
{
....
}

//Tony
 
P

Peter Duniho

[...]
Dictionary<string, Car> directory = new Dictionary<string, Car>();
Now to my question assume that you have a derived class called BMW below
the
base class Car.

Is it then legal to use BMW instead of Car because BMW is a Car

Yes. Though, I'm not sure why you're asking the question here. You could
have just compiled some code that adds a BMW to a Dictionary that has Car
as the type for the value and see what happens.

In general, if the only question is "is it legal?", usually you can answer
that yourself, and much more quickly than posting to a newsgroup and
waiting for someone else to tell you. Just try it. If it's legal (i.e.
the language allows it), it will work. If it's not, it won't.

Pete
 
C

christery

Is it then legal to use BMW instead of Car because BMW is a Car

If bmw extends or overrides car then I suppose I wuld have to use bmw
otherwise didnt bother to derive that class.. if its not abstract
(thinking java but that should apply)
otherwise I would use my = new volvo(); // ... ;) and they say
nerds cant have fun...
 
L

Lasse Vågsæther Karlsen

Tony said:
Hello!

Assume you have this generic Dictionary class with key, value pair the first
part is the key and the second part is the value part.
The key value is a string and the value part is the Car.
Dictionary<string, Car> directory = new Dictionary<string, Car>();
Now to my question assume that you have a derived class called BMW below the
base class Car.

Is it then legal to use BMW instead of Car because BMW is a Car or are you
obliged to use exactly
the same type (here Car) as the one you used when you instansiated the
object directory of type Dictionary.

I assume that this is the main point of using generics to use exactly the
same type because if this was not the case you could all the same use the
general class.

This is actually a question about polymorphism and inheritance, rather
than a question about generics.

A class (BMW) that inherits from another class (Car), is, if you think
of the classes as categories, of that base category.

A BMW is a Car.
Which leads to: Anywhere you can talk about a Car, you can use a BMW.

This also holds true for generics. The only difference is when you get
to covariance. In other words, while you can do this:

Car c = new BMW();

or this:
BMW b = new BMW();
MethodThatTakesCarParameter(b);

you can not do this:

List<Car> c = new List<BMW>();

or this:
List<BMW> b = new List<BMW>();
MethodThatTakesAListOfCars(b);

This is (apparently) supported by the runtime, but not by the C#
programming language.

The main reason is that if the above was legal, you could do this:

List<Car> c = new List<BMW>();
c.Add(new Car()); // list is only supposed to store BMW's
 
J

Jon Skeet [C# MVP]

you can not do this:

List<Car> c = new List<BMW>();

or this:
List<BMW> b = new List<BMW>();
MethodThatTakesAListOfCars(b);

This is (apparently) supported by the runtime, but not by the C#
programming language.

Nope, that isn't supported by the runtime either. Only covariance/
contravariance of delegates and interfaces is supported - and only
when it's proved to be safe.

Jon
 
A

Andrus

Nope, that isn't supported by the runtime either. Only covariance/
contravariance of delegates and interfaces is supported - and only
when it's proved to be safe.

This is supported somewhat in .NET 3.5 runtime.

3.5 has Cast<>() method on IQueryable.

So MS tries to fix this introducing methods for specific type.

Andrus.
 
J

Jon Skeet [C# MVP]

Andrus said:
This is supported somewhat in .NET 3.5 runtime.

3.5 has Cast<>() method on IQueryable.

That's not runtime support - that's framework support. (And it's
available on IEnumerable too.)

There's a subtle but important difference between what is supported by
the framework and what is supported by the runtime. The Cast method has
to act on every object it sees, whereas I believe runtime support would
be along the lines of an implicit reference conversion - "I can always
So MS tries to fix this introducing methods for specific type.

Well, that's the *current* fix :)
 
A

Andrus

3.5 has Cast said:
That's not runtime support - that's framework support. (And it's
available on IEnumerable too.)

There's a subtle but important difference between what is supported by
the framework and what is supported by the runtime. The Cast method has
to act on every object it sees, whereas I believe runtime support would
be along the lines of an implicit reference conversion - "I can always
treat an IEnumerable<string> as an IEnumerable<object>; no further
checks required".

How Cast<TEntity> method is implemented ?

Does it perform memberwize casting: loop over source and cast every member
to destination type ?

IEnumerable<TDest> Cast( IEnumerable<TSource> src ) {
List<TDest> dest = new ListList<TDest> ();
foreach ( TSource e in src ) {
dest.Add( (TDest) e );
}
return dest;
}

?
Andrus.
 
J

Jon Skeet [C# MVP]

Andrus said:
How Cast<TEntity> method is implemented ?

I don't know, to be honest.
Does it perform memberwize casting: loop over source and cast every member
to destination type ?

IEnumerable<TDest> Cast( IEnumerable<TSource> src ) {
List<TDest> dest = new ListList<TDest> ();
foreach ( TSource e in src ) {
dest.Add( (TDest) e );
}
return dest;
}

?

Just a cast doesn't work - you can't perform casts like that. The
compiler needs to know what kind of conversion it would be performing.

I suspect it needs to do somewhat more. You could always debug into the
code and have a look :)
 
L

Lasse Vågsæther Karlsen

Jon said:
Nope, that isn't supported by the runtime either. Only covariance/
contravariance of delegates and interfaces is supported - and only
when it's proved to be safe.

Jon

Ok, I put "apparently" in parenthesis to highlight that I might not be
correct on that issue :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top