Re: Abstract class variables question
- From: "tshad" <tfs@xxxxxxxxxxxxxx>
- Date: Mon, 19 Nov 2007 00:49:48 -0800
"Peter Duniho" <NpOeStPeAdM@xxxxxxxxxxxxxxxx> wrote in message
news:2007111819511975249-NpOeStPeAdM@xxxxxxxxxxxxxxxxxx
On 2007-11-18 12:55:03 -0800, "tshad" <tfs@xxxxxxxxxxxxxx> said:
I think I understand boxing a little better now.
After reading your information and a couple of other articles - I think I
have a better idea what it is and why it is used. The problem was the
WHY.
I had seen other articles on the HOW but not much on the why:
int i,j;
object o = i; // Boxed
j = (object) o/ // unboxed.
This shows how it is done but not why you would use it.
Has the "why" been adequately explained yet? Or would you like
elaboration on that?
I am always looking for different views on the issue as each one helps a
little more, as in this case. This excercise and various articles have
helped me to understand it.
I guess the question is not only WHY but WHEN. Obviously, it is the case
here.
I did try this class with my data in place of my old NullHandler and I think
this class is going to do what I need.
Here was what I found:
Instead of:
NullHandler.GetValueFromDbObject((object)user["UserID"],ref userID);
I found I can do:
StringType lastName = new StringType();
StringType email2 = new StringType();
lastName.Data = (object)dbReader["FirstName"];
email2.Data = (object)dbReader["Email2"];
At first I tried to cast them as string:
lastName.Data = (string)dbReader["FirstName"];
email2.Data = (string)dbReader["Email2"];
And that works fine, unless the value is null. In that case I get an error:
"Specified cast is not valid".
Not sure why that is since a string can be null.
string stemp;
stemp = null;
Works fine. So why would (string)dbReader["Email2"] not work?
Casting it as (object) works whether it is a null or not. But when it was
cast as an object I did get an error at the ValidateType function at the
line:
if (!typeRequired.IsInstanceOfType(obj))
{
throw new ArgumentException("assigned value type of " +
obj.GetType().Name + " is incompatible with required type of " +
typeRequired.Name);
}
The error is:
"assigned value type of DBNull is incompatible with required type of
String"
Once I saw that I realized I would need to change the line before call to
the ValidateType function to:
if ((value != null) && (value != DBNull.Value))
{
_ValidateType(value);
}
and that fixes that.
I also have to look at the TypedData properties also as they also give me
the Invalid Cast for it also - which if you remember is:
get { return (string)Data; }
4) String types are already reference types and all we are doing when we
do
"object o = str" is create a new reference/pointer that points to the
object
on the heap.
Depends on your definition of "create". My view is that the assignment
doesn't create anything. The source and destination already exist, and
the reference is copied from one to the other.
But yes, in another sense a new copy of the reference is "created",
replacing whatever was in the variable before (and in that sense, if the
reference is "created", the previous value of the variable is
"destroyed").
What I meant was that the statement creates a new reference "o" that will
point to the same location as "str" which is where the string actually is.
Right.In the case of a non-string object, the object is the same but we have 2
pointers to that same object. If the object changes value and both
references point to the same object, they will be the same.
Well, that would be true for a string object too, if there was any way to
actually change a string.
But what I was saying that it isn't the same as the string since if you
change the string in any way "another" object is created and then one of the
references would be pointing at the original string and the other reference
would be pointing at the new string.
Likewise, if you assign a new reference to a reference type variable, that
doesn't affect other variables that might have referenced the same object
that variable previously referenced. For example:
object A = new object();
object B = A;
A = new object();
Right, but that is because YOU are creating a new object. In the string
case, the new object is being created because you changed the string. In a
non-string object, this would not be the case. If you said B.something =
15, both A and B would still point to the same object.
That's just like the string case. Assigning a new reference to A doesn't
change what B references. This works for _any_ reference type variable.
The thing about the string class is that assigning a new string instance
to a string type variable is the _only_ way to change the string value of
that variable. Mutable classes, you can call some method or set a
property or something like that, and that will change the instance itself,
without requiring you to assign a new instance of the class to a variable.
I realize that the distinction might seem subtle, or even pedantic. But I
think it's a very important distinction. In particular, it's very
important to understand that with respect to the code we've seen in this
thread, the string class isn't really so different from other classes.
Because it's immutable, you _have_ to write code like we've seen here,
while other classes might provide other options. But even with a mutable
class, if you write code like we've written here, it'll behave just like
the string class (except of course for the one example I showed
specifically designed to change a class instance without reassiging the
variable).
Right.
You are talking about a value type, I assume. Since you will have a value
type variable and a reference type variable.
But in the case of a string, which is immutable, the 1st reference would
point to the first string and the 2nd reference (after the string is
changed) will point to the new string. And that would be the case, even
if
we didn't move it to a new object.
Even if we didn't move what to a new object?
Not sure what I meant there either :(
As far as "the string is changed", I think it's important to understand,
the original string isn't changed. You create a whole new string
instance, and the string type variable itself is changed to reference the
new string instance.
Again, maybe it seems pedantic, but I think it's important to understand
the difference between the variable referencing some data and the data
itself, and along with that to make sure the language one is using is
clear about that difference.
I agree.
string A = "something";
string B;
B = A;
A += " Else";
gives me the same result as:
string s1 = "something";
object o1 = s1;
s1 += " Else";
Where A <> B and o1 <> s1 because in both cases a new string is created
even
though we think we are changing the strings.
Well, you might think you are changing the strings. :)
Seriously though, it is practically always the case that when you are
writing an assignment to a reference, you're replacing the reference held
by the variable. The obvious exception is of course where for whatever
reason your code sometimes assigns a reference to a variable when it
already holds that reference. Another example, one that I hope is
_extremely_ uncommon, would be in the case of an operator that's
overloaded to return the original instance reference for one of the
operands.
But as a general rule of thumb, changing an instance will go through some
member of the instance, while changing a reference value will involve the
assignment operator. The string class has no member of the class that
allows the instance to be changed, which is what makes it immutable. But
the "changing a reference value" is the same for the string class as it is
for any other class, immutable or not.
I agree. A reference is a reference.
[...]
The boxing of the variable "i" does not in any way relate the variable
"i"
to something on the heap. It _copies_ the value from the variable "i"
into a completely new data structure. Once this is done, "i" is
completely irrelevant to the reference instance. It's very misleading
to
refer to that instance as being "i on the heap".
It may be misleading but I think the value that gets copied does get
copied
to the heap. But in the case of an Class Object that is already on the
heap, you are copying the value from a heap location to a heap location.
I think you lost me. I'm not sure what "Class Object" refers to (maybe
something in the previously referenced web page?), but assuming it's a
class, it's a reference type and assigning the reference to the instance
to any variable just copies the reference, not the class instance itself.
I was just making the point that a value type gets copied from the stack to
the heap. But if the value type is in an object and gets boxed there, it is
already on the heap (since it is part of the object) and it is actually
getting copied from the heap to another location on the heap. Not really
important just that fact that a value type is not always on the stack (if it
is part of an object). That wasn't made clear in either of the articles.
If that's what you meant, then I'll agree with that. :)
[...]
The current value of "i" is passed into the constructor, where it's
copied
to the private field "_value". You can read it back out, which then
copies the value from the private field to wherever you assign it. But
"i"
is only relevant when the instance is first constructed, and there only
as
it's passed by value to the constructor.
So in this case I have "i" which is a value Type and boxed.i (if i were
public) which are completely different even if they have the same value
at
the start. If I then change "i" to 30, boxed.i will still = 5.
Exactly.
[...]
In that case, your statement that "B will be 'something'" is not true.I got it.
B
continues to reference the same instance as A, and having changed that
instance so that it contains "something else" instead, the instance of
Mutable that B refers to will contain "something else" (because it's the
same instance).
If the string is inside the object and A and B both pointed at the
object
even if the string changed INSIDE the object, since A and B are both
pointing at the same object with the string changed and therefore
A.String
and B.String would be the same.
Right.
But in the above case:
string A = "something";
object B;
B = A;
A = "Something Else"
You really do have 2 references to 2 different objects (a string and and
an
object) and NOT 2 references to the same object.
Well, the _variable_ type is object for the second reference, but after
the third line ("B = A") you still only have one object: the original
string ("something").
Using the variable B you could only do things with the instance that are
defined in the class Object. But the instance is still a string.
After the fourth line, you now have two objects, both of them strings.
The original string is now only accessible via a variable typed as Object,
so you can only use the things defined in the Object type. But you could
cast the reference held in B back to a string, and you'd then be able to
do all the things the class String defines with the instance.
And because of the way a
string works when you change A you actually get a 3rd object
No, only a second object. See above.
You're right.
The first string won't go away because B is pointing at it, so we only have
2 objects.
[...]
The int type and string type are _definitely_ handled differently. An
int
is a value type, and so to assign an int instance to an object variable,
it has to be boxed. But a string is a reference type, and assigning a
string instance to an object variable requires no such work.
But the string is a special type of reference type (immutable) in that
you
can't just assign the reference to another string and assume they will
stay
the same, since any change to the string will now change the object the
reference is pointing to. Correct?
Sort of. I think I explained this above, but just to reiterate:
Knowing that the String class is immutable, you know that if two or more
variables do reference the same instance, that that instance will never
change.
In that respect it's not correct to write "any change to the string",
since there's no such thing. A string is immutable; there can be no
change to the string.
I think it is just the language here. I agree that you can't change the
string. I was just saying that if you were trying to make a change to the
string (any change) would just create another string/object with the result.
Even though it looks like the string changed - it actually didn't you are
now pointing at a new location with the changed string.
Tom
.
- Follow-Ups:
- Re: Abstract class variables question
- From: Peter Duniho
- Re: Abstract class variables question
- References:
- Abstract class variables question
- From: tshad
- Re: Abstract class variables question
- From: Peter Duniho
- Re: Abstract class variables question
- From: tshad
- Re: Abstract class variables question
- From: Peter Duniho
- Re: Abstract class variables question
- From: tshad
- Re: Abstract class variables question
- From: Peter Duniho
- Re: Abstract class variables question
- From: tshad
- Re: Abstract class variables question
- From: Peter Duniho
- Re: Abstract class variables question
- From: tshad
- Re: Abstract class variables question
- From: Peter Duniho
- Re: Abstract class variables question
- From: tshad
- Re: Abstract class variables question
- From: Peter Duniho
- Re: Abstract class variables question
- From: tshad
- Re: Abstract class variables question
- From: Peter Duniho
- Re: Abstract class variables question
- From: tshad
- Re: Abstract class variables question
- From: Peter Duniho
- Re: Abstract class variables question
- From: tshad
- Re: Abstract class variables question
- From: Peter Duniho
- Abstract class variables question
- Prev by Date: Re: namespaces, projects and solutions
- Next by Date: Re: Order or DbLinq properties in code generated by pgsqlmetal
- Previous by thread: Re: Abstract class variables question
- Next by thread: Re: Abstract class variables question
- Index(es):
Relevant Pages
|