using ArrayList with object

T

Tony Johansson

Hello!

The question is about this assignment statement Person pp = arrList[0];
I know that to correct the error I have to write Person pp =
(Person)arrList[0];

But my question is the following.
This statement give compile error. I have always thought that the compiler
doesn't see these kind of error which
therefore only give run time error of type InvalidCastException.

I'm I wrong in some way. I have even read this in some books that the
compiler only see the type when
taken from the collection and assigning to a new object type.

class Program
{
ArrayList arrList = new ArrayList();

public Program()
{
arrList.Add(new Person("123456-1234", "Nisse", 14));
arrList.Add(new Person("987654-4321", "Pelle", 15));
arrList.Add(new Person("563423-7612", "Stina", 35));

Person pp = arrList[0];
}

static void Main(string[] args)
{
Program prog = new Program();
}
}

class Person
{
private string pers_nr;
private string name;
private int age;

public Person(string pers_nr, string name, int age)
{
this.pers_nr = pers_nr;
this.name = name;
this.age = age;
}

public string Pers_nr
{
get { return pers_nr; }
set { pers_nr = value; }
}

public string Name
{
get { return name; }
set { name = value; }
}

public int Age
{
get { return age; }
set { age = value; }
}

public override string ToString()
{
return string.Format("Pers_nr = {0} Name = {1} Age = {2}",
Pers_nr, Name, Age);
}
}

//Tony
 
P

Peter Duniho

Hello!

The question is about this assignment statement Person pp = arrList[0];
I know that to correct the error I have to write Person pp =
(Person)arrList[0];

That's right. ArrayList returns an object, so you have to cast back to
the original type.
But my question is the following.
This statement give compile error.

Which statement? The code you posted doesn't have a cast, so yes...you'll
get a compiler error.

Do you have an example where you _are_ doing the cast, and yet still get
an error?

Pete
 
T

Tony Johansson

Hello!

So you mean that a compile error will always be given when assigning an
object to for example a Person like this
Person pp = arrList[0];
So when will this InvalidCastException be given ?

So what the book was writing telling me that this statement Person pp =
arrList[0];
will compile but give a run time error of type InvalidCastException is
completely wrong.


//Tony


"Peter Duniho" <[email protected]> skrev i meddelandet
Hello!

The question is about this assignment statement Person pp = arrList[0];
I know that to correct the error I have to write Person pp =
(Person)arrList[0];

That's right. ArrayList returns an object, so you have to cast back to
the original type.
But my question is the following.
This statement give compile error.

Which statement? The code you posted doesn't have a cast, so yes...you'll
get a compiler error.

Do you have an example where you _are_ doing the cast, and yet still get
an error?

Pete
 
J

Jon Skeet [C# MVP]

Tony Johansson said:
So you mean that a compile error will always be given when assigning an
object to for example a Person like this
Person pp = arrList[0];
Yes.

So when will this InvalidCastException be given ?

If you do:

Person pp = (Person) arrList[0];

but actually arrList[0] isn't a Person, you'll get an
InvalidCastException.
So what the book was writing telling me that this statement Person pp =
arrList[0];
will compile but give a run time error of type InvalidCastException is
completely wrong.

If the book actually says that, then it is wrong. Could you quote the
actual text of the book?
 
T

Tony Johansson

Hello!

The book is called Microsoft Visual C# 2005 step by step.
The example in the the book is based on Queue which store object just the
same as ArrayList does.
Here is a translation from Swedish to English. In some places the text say
it will cause compile error and in other places
say that no compiler error will be given but only run time exception.
In some places have I noticed that the text is completely wrong ?

Here start the translated text
"Because methods Enqueue and Dequeue both work with object they can be used
in connection with queue of type
Circle, PhoneBook Clock and other types. It's important to notice that the
value which is returned by method Dequeue must be
converted to a suitable value because the compiler will not automatically
convert from type object. If the returned value
is not type convered as in the example below will a compile error exist with
message "cannot implicitely convert type object to
Circle".
Circle myCircle = new Circle();
myQueue.Enqueue(myCircle);
....
myCircle = (Circle)myQueue.Dequeue(); // Type convert is mandatory

This kind of explicit type convert will remove most of the flexibility that
the object type has.
It's far to easy to write code like this.
Queue myQueue = new Queue();
Circle myCircle = new Circle();
....
Clock myClock = (Clock)myQueue.Dequeue();

Even if this code can be compiled it's not valid and will throw an exception
of type
System.InvalidCastException when the program is running.
The error is caused by trying to reference to a Circle in a variable of type
Clock
These two types is not compatible. The error will not be detected until run
time because the compiler doesn't have enough
information. The compiler can only decide the type of the object when taken
from the queue when the program is running."

//Tony

Jon Skeet said:
Tony Johansson said:
So you mean that a compile error will always be given when assigning an
object to for example a Person like this
Person pp = arrList[0];
Yes.

So when will this InvalidCastException be given ?

If you do:

Person pp = (Person) arrList[0];

but actually arrList[0] isn't a Person, you'll get an
InvalidCastException.
So what the book was writing telling me that this statement Person pp =
arrList[0];
will compile but give a run time error of type InvalidCastException is
completely wrong.

If the book actually says that, then it is wrong. Could you quote the
actual text of the book?
 
J

Jon Skeet [C# MVP]

Tony Johansson said:
The book is called Microsoft Visual C# 2005 step by step.
The example in the the book is based on Queue which store object just the
same as ArrayList does.
Here is a translation from Swedish to English. In some places the text say
it will cause compile error and in other places
say that no compiler error will be given but only run time exception.
In some places have I noticed that the text is completely wrong ?

It looks okay to me, although the second code bit should enqueue the
circle.

Which bit do you think is specifically wrong?
 
T

Tom P.

Hello!

The book is called Microsoft Visual C# 2005 step by step.
The example in the the book is based on Queue which store object just the
same as ArrayList does.
Here is a translation from Swedish to English. In some places the text say
it will cause compile error and in other places
say that no compiler error will be given but only run time exception.
In some places have I noticed that the text is completely wrong ?

Here start the translated text
"Because methods Enqueue and Dequeue both work with object they can be used
in connection with queue of type
Circle, PhoneBook Clock and other types. It's important to notice that the
value which is returned by method Dequeue must be
converted to a suitable value because the compiler will not automatically
convert from type object. If the returned value
is not type convered as in the example below will a compile error exist with
message "cannot implicitely convert type object to
Circle".
Circle myCircle = new Circle();
myQueue.Enqueue(myCircle);
...
myCircle = (Circle)myQueue.Dequeue(); // Type convert is mandatory

This kind of explicit type convert will remove most of the flexibility that
the object type has.
It's far to easy to write code like this.
Queue myQueue = new Queue();
Circle myCircle = new Circle();
...
Clock myClock = (Clock)myQueue.Dequeue();

Even if this code can be compiled it's not valid and will throw an exception
of type
System.InvalidCastException when the program is running.
The error is caused by trying to reference to a Circle in a variable of type
Clock
These two types is not compatible. The error will not be detected until run
time because the compiler doesn't have enough
information. The compiler can only decide the type of the object when taken
from the queue when the program is running."

//Tony

Jon Skeet said:
Tony Johansson said:
So you mean that a compile error will always be given when assigning an
object to for example a Person like this
Person pp = arrList[0];
So when will this InvalidCastException be given ?
If you do:
Person pp = (Person) arrList[0];
but actually arrList[0] isn't a Person, you'll get an
InvalidCastException.
So what the book was writing telling me that this statement Person pp =
arrList[0];
will compile but give a run time error of type InvalidCastException is
completely wrong.
If the book actually says that, then it is wrong. Could you quote the
actual text of the book?

This looks like a perfect example of what Jon was saying: If you only
put (Circle) objects in the Queue then the cast is a technicallity to
us since we know all the "Objects" are really "Circles".

BUT if you put more than one kind of object (say a Circle and two
Clocks) in the queue then be careful when you dequeue because if you
dequeue a Clock into a Circle type variable you'll get an
InvalidCastException.

Look the text over again and you'll see that the examples that compile
always have a cast, what the author is saying is be careful that you
are casting them correctly because the compiler can't tell what will
eventually end up in the queue.

Tom P.
 
P

Phil Wilson

If the book also covers generic collections then you might find that
sometimes List <Person> is the kind of thing you want to use.
--
Phil Wilson
[MVP Windows Installer]

Tony Johansson said:
Hello!

So you mean that a compile error will always be given when assigning an
object to for example a Person like this
Person pp = arrList[0];
So when will this InvalidCastException be given ?

So what the book was writing telling me that this statement Person pp =
arrList[0];
will compile but give a run time error of type InvalidCastException is
completely wrong.


//Tony


"Peter Duniho" <[email protected]> skrev i meddelandet
Hello!

The question is about this assignment statement Person pp = arrList[0];
I know that to correct the error I have to write Person pp =
(Person)arrList[0];

That's right. ArrayList returns an object, so you have to cast back to
the original type.
But my question is the following.
This statement give compile error.

Which statement? The code you posted doesn't have a cast, so yes...you'll
get a compiler error.

Do you have an example where you _are_ doing the cast, and yet still get
an error?

Pete
 
T

Tony Johansson

Hello!

I mixed up two different things in the text.
There is no wrong text any more because you informed me with this text in
your mail
So when will this InvalidCastException be given ?
If you do:
Person pp = (Person) arrList[0];
but actually arrList[0] isn't a Person, you'll get an
InvalidCastException.

//Tony
 
J

Jon Skeet [C# MVP]

Tony Johansson said:
I mixed up two different things in the text.
There is no wrong text any more because you informed me with this text in
your mail

Goodo :)
 
P

Peter Duniho

The book is called Microsoft Visual C# 2005 step by step.
The example in the the book is based on Queue which store object just the
same as ArrayList does.
Here is a translation from Swedish to English. In some places the text
say
it will cause compile error and in other places
say that no compiler error will be given but only run time exception.
In some places have I noticed that the text is completely wrong ?

You should post those examples then, as you didn't post any text that was
wrong.

In the text, where it says a compile error will occur, it's talking about
trying to assign an instance of "Object" to an instance of something
else. And it's correct...without an explicit cast, a compiler error will
occur.

Where is says no compile error will occur, it's talking about what happens
once you _do_ use an explicit cast. This is an entirely different
situation, and is completely consistent with the text's previous statement
that an explicit cast is required to avoid a compile error. It goes on to
explain that if in fact the type is not the correct type in the collection
(as would be the case if you've added a Circle to the collection but then
tried to cast that to a Clock), you would get an error _but only at
run-time_. That's also correct.

A simpler example would be something like this:

Circle circle = new Circle();
Object obj = circle;
Clock clock = (Clock)obj;

The compiler is perfectly happy to compile that. But at run-time you are
guaranteed to fail with an invalid cast exception. This is the error that
the text is warning you against.

Basically, the text you did post doesn't say what you said it says, and it
is in fact correct.

The text you posted specifically says that because the Queue.Dequeue()
method returns an object, you must cast it. For the Queue class it's
talking about, it's exactly correct. Even the discussion regarding the
risks of doing that is correct. That is, when using the non-generic Queue
class, just as with the ArrayList, there's nothing to protect you at
compile time against putting the wrong type in the collection, or
incorrectly casting an instance retrieved from the collection.

If you want compile-time protection, you should use the generic classes
Queue<T> and List<T>. With those, you specify the type contained in the
collection when you declare the collection instance, and no casting is
necessary when retrieving instances from the collection, and trying to
retrieve something into the wrong type will generate a compiler error. In
addition, because adding to the collections is also typed more
specifically than "Object", the compiler will only let you add things of
the correct type to the collection.

Pete
 
B

Ben Voigt [C++ MVP]

Tony Johansson said:
Hello!

The book is called Microsoft Visual C# 2005 step by step.
The example in the the book is based on Queue which store object just the
same as ArrayList does.

No book covering 2005 should be using the untyped collections. We have
List<T> and Stack<T> for a reason.
 

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

Top