Re: Can generics really produce strongly typed collections?
- From: beginwithl@xxxxxxxxx
- Date: Thu, 22 Jan 2009 15:58:01 -0800 (PST)
hi Pete
On Jan 23, 3:00 am, "Peter Duniho" <NpOeStPe...@xxxxxxxxxxxxxxxx>
wrote:
On Thu, 22 Jan 2009 13:21:48 -0800, <beginwi...@xxxxxxxxx> wrote:As I see it, the term strongly typed depends on the specific code we
1) Do we consider a collection to be strongly typed only if the
insertion of an item ( that is of incompatible type ) can be
determined at compile time?
No. Consider:
object obj = (object)5;
List<String> lstr = new List<String>();
lstr.Add((String)obj);
The compiler won't detect the bug at compile time. But the collection is
still (IMHO) strongly typed, and a run-time exception will be thrown
(during the cast, before the Add() method is even called).
are considering. If we just look at definition of List<T> class, then
we can say that that piece of code ( thus class List<T> ) is strongly
typed. But when we try to decide if the following piece of code is
strongly typed :
object obj = (object)5;
List<String> lstr = new List<String>();
lstr.Add((String)obj);
then we could claim that the above code, as a whole, isn’t strongly
typed ( here I’m using the term strongly typed to refer only to
compile-time detection of a bug ).
For example: we could build a non generic custom collection that
allows only items of type A to be inserted by the user.
But what if this custom collection would only check at run time
( perhaps using try-catch clause ) if inserted item is of specified
type?
Do we still call this collection strongly typed?
In some sense of the phrase, it's strongly typed. I prefer "strongly
typed" to describe something that is strong both at compile and run-time,
but it's not a well-defined term, so you may find alternate definitions,
or even use alternate definitions yourself.
As long as the person with whom you're communicating agrees on the same
definition you're using, that's fine.
2) Assume class B is derived from A
If a collection implements IEnumerator<T> interface, the ‘Current’
property returns an item of type T ( or type derived from T ), and
thus casting to actual type is not needed. That is considered strongly
typed code.
Yes.
a) But explicit casting is still needed if T is of type A, but foreach
variable Variab is of type B!
foreach( B Variab in our_Collection ) {…}
b) and if it happens that an item in this collection, which foreach
will try to cast to B ( in order to assign it to Variab ), is actually
of type A, an exception will occur!
Thus, I don’t see how we can claim that enumerator is strongly-typed?!
See above. The "foreach" statement specifically behaves in the way you
describe, and an explicit cast (even an implicit explicit cast :) )
overrides the compiler's normal type rules. Overriding the rules doesn't
mean the thing you overrode wasn't strongly typed. It means you overrode
the strong typing.
Note that due to the actual strong typing, at run-time you still get an
exception. You're not allowed to try to use something as a B if it's not
a B. That's strong typing.
Yeah, but in situation you're describing I interpret the term ‘strong
typing’ in a more general sense, meaning that the ability of run-time
to notice illegal cast is due to C# being strongly typed language, and
thus any code written in C# is in that sense strongly typed.
2) Next question is basically the same as previous one, but now I’m
asking about generics and strong typing in general:
Say we have a generic collection of type Some_Colection<A>, which only
stores items of type A or those derived from A. If we have classes of
type B and C ( both being derived from A ), then we may store items of
both types into some_collection<A>.
But again, chances are a user may try to do some sort of operations on
item stored in this collection, thinking it is of type B but is really
of type C and as a result an exception will be thrown. In other
words, we did manage to ensure type safety when dealing with types
not_of_type_A/not_derived_from_A, but we are still dealing with unsafe
code when it comes to operating on items ( stored inside this
collection ) derived from A?!
The only way you can get into that situation is to insert a bug in your
code, by overriding the type safety provided for you. Doing that doesn't
mean the things aren't type safe. It means that they are but you have
intentionally bypassed that type safety.
* But then we could argue that non generic collections are also type
safe, but we (users) are intentionally bypassing that type safety by
trying to cast returned item ( which is of type object ) into some
derived type, and in doing so we are risking an illegal cast.
* As I see it, by using generic collections we simply lessen the
chances that users will try to perform an illegal cast
3)
a) Say we have a collection that implemented IEnumerable<string>. How
does foreach statement figure out that this particular collection
implemented IEnumerable<string> and not, for example, IEnumerable<int>
or whatever?
It all depends on how you declare the interfaces and their
implementations. But, the compiler uses only the implicitly implemented
interface, assuming one exists. If IEnumerable<string> is the implicitly
implemented one, that's the one you get. If all your interface
implementations are explicit, then it will look for a generic one and if
it finds one (and _only_ one), it will use that.
Note that there are limits to what the compiler can do with "foreach". If
you implement IEnumerator implicitly and IEnumerator<string> explicitly,
then "foreach" will find the non-generic version in a "foreach" that tries
to use "int", and _it will use it_.
You mean if variable ‘Variab’ in foreach is of type 'int', but foreach
calls non generic version of 'Current', then it will try to cast an
item ( returned by IEnumerator version of 'Current' ) into 'int', and
since that returned item is actually 'string', it will throw an
exception:
foreach( int Variab in Generic_string_Collection ) {…}
You won't get an error until
run-time. Even if you implement IEnumerable<string> implicitly and
IEnumerable explicitly, if you cast your collection to IEnumerable,
"foreach" will happily use that interface for the enumeration (and again,
throw an exception at run-time, since in reality the collection isn't a
collection of ints).
By casting my collection to IEnumerable you mean:
foreach( int Variab in ( IEnumerable )Some_Colection ) {…}
then foreach will of course call IEnumerable version of 'Current'
property?
Finally note that if you attempt to implement multiple generic
IEnumerable<T> interfaces on a class, the compiler will require that you
specifically cast your collection to the interface you intend to use.
You mean I will have to do the following:
foreach( int Variab in ( IEnumerable<some_type> ) Some_Colection ) {…}
thanx mate
.
- Follow-Ups:
- Re: Can generics really produce strongly typed collections?
- From: Peter Duniho
- Re: Can generics really produce strongly typed collections?
- References:
- Can generics really produce strongly typed collections?
- From: beginwithl
- Re: Can generics really produce strongly typed collections?
- From: Peter Duniho
- Can generics really produce strongly typed collections?
- Prev by Date: Re: Compiler and it’s (in)ability to detect incompatible assignments
- Next by Date: Re: CPU load generator
- Previous by thread: Re: Can generics really produce strongly typed collections?
- Next by thread: Re: Can generics really produce strongly typed collections?
- Index(es):
Relevant Pages
|
Loading