By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,668 Members | 1,503 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,668 IT Pros & Developers. It's quick & easy.

What does it mean?

P: n/a
Hi,

Would someone explain the following coding more detail for me? What's the
( ) for?
CurrentText = (TextBox)e.Item.Cells[i].Controls[0];
Thanks.

Jason
Nov 17 '05 #1
Share this Question
Share on Google+
13 Replies


P: n/a
This is a cast.(type casting), have a look at this article to see if it
explains things for you
http://www.csharphelp.com/archives2/archive336.html

Hope this helps

Publicjoe

C# Tutorial at http://www.publicjoe.f9.co.uk/csharp/tut.html
C# Ebook at http://www.publicjoe.f9.co.uk/csharp/samples/ebook.html
VB Tutorial at http://www.publicjoe.f9.co.uk/vbnet/vbnet.html
VB Ebook at http://www.publicjoe.f9.co.uk/vbnet/samples/ebook.html
Mirrors at http://dowhileloop.com/publicjoe/ and
http://publicjoe.dowhileloop.com

"Jason Huang" <Ja************@hotmail.com> wrote in message
news:Ol*************@TK2MSFTNGP12.phx.gbl...
Hi,

Would someone explain the following coding more detail for me? What's the
( ) for?
CurrentText = (TextBox)e.Item.Cells[i].Controls[0];
Thanks.

Jason

Nov 17 '05 #2

P: n/a

"Jason Huang" <Ja************@hotmail.com> wrote in message
news:Ol*************@TK2MSFTNGP12.phx.gbl...
Hi,

Would someone explain the following coding more detail for me? What's the
( ) for?
CurrentText = (TextBox)e.Item.Cells[i].Controls[0];


Typecasting, so that the result of 'e.Item.Cells[i].Controls[0];' is an
object of the type 'TextBox'

--
Søren Reinke
www.Xray-Mag.com/ - Your free diving magazin on the net.
Current issue Diving in North America, 99 pages.
Download it in PDF
Nov 17 '05 #3

P: n/a
Looks like 'e' is a grid or list of some kind... possibly a third party
control.
The Item method allows you to dig into the list elements of the control.

Cells[i] is an array of cells or list elements. This looks like a single
list or a one-column grid?
So, the value [i] selects the "i"th element in the list (usually counting
from zero).
Note: if the list does not have "i" elements in it, then this statement will
generate an error.

It looks like each cell in your control can hold multiple controls
(perfectly valid). However, the original programmer expects that there is
at least one control in that cell. s/he refers to that first control in the
cell as controls[0]. Note: if the cell does not contain a control, this
statement will generate an error.

The same developer expects that the first control is a text box. Note: if
it is not a textbox, this statement will generate an error.

The developer used casting to let the language know that it should treat the
first control, in the controls list, as a text box.
That value is assigned to the variable CurrentText

Note: if the variable CurrentText is a string variable, then the original
developer should probably have called a method on the TextBox to return the
actual text contents. That is probably the intent, although it isn't coded
that way.

Therefore, assuming this statement compiles, this statement will return the
textbox control from a cell in an editable list or grid, or it throws one of
many runtime errors.

--
--- Nick Malik [Microsoft]
MCSD, CFPS, Certified Scrummaster
http://blogs.msdn.com/nickmalik

Disclaimer: Opinions expressed in this forum are my own, and not
representative of my employer.
I do not answer questions on behalf of my employer. I'm just a
programmer helping programmers.
--
"Jason Huang" <Ja************@hotmail.com> wrote in message
news:Ol*************@TK2MSFTNGP12.phx.gbl...
Hi,

Would someone explain the following coding more detail for me? What's the
( ) for?
CurrentText = (TextBox)e.Item.Cells[i].Controls[0];
Thanks.

Jason

Nov 17 '05 #4

P: n/a
The previous posts are correct and sufficient.

Might I recommend that you use "as" instead of a cast. This is for
converting compatible types. It will only perform reference conversions and
boxing conversions. The "as" is equivalent to:

expression is type ? (type) expression : (type) null

Note the extra safety in checking the type prior to performing the
conversion. Should the expression in the above not be of the type you are
looking for, it returns null. If you cast like this:

(type) expression

and the type in the expression is not compatible with type, then a
System.InvalidCastException exception will be thrown.

Hope this helps...

Frisky
"Jason Huang" <Ja************@hotmail.com> wrote in message
news:Ol*************@TK2MSFTNGP12.phx.gbl...
Hi,

Would someone explain the following coding more detail for me? What's the
( ) for?
CurrentText = (TextBox)e.Item.Cells[i].Controls[0];
Thanks.

Jason

Nov 17 '05 #5

P: n/a
Frisky <Fr***********@NorthPole.net> wrote:
The previous posts are correct and sufficient.

Might I recommend that you use "as" instead of a cast. This is for
converting compatible types. It will only perform reference conversions and
boxing conversions. The "as" is equivalent to:

expression is type ? (type) expression : (type) null

Note the extra safety in checking the type prior to performing the
conversion. Should the expression in the above not be of the type you are
looking for, it returns null. If you cast like this:

(type) expression

and the type in the expression is not compatible with type, then a
System.InvalidCastException exception will be thrown.


"as" and casting serve slightly different purposes. When it is a
programming error for the value of a variable *not* to be a reference
to a certain type of object, I use a cast. If it's not an error, and I
just want to do something different if it's not an appropriate
reference, that's when as is useful.

For instance, taking values out of a private ArrayList, I'd always use
a cast - if the value isn't of the right type, I've got an error
elsewhere in my code, and an InvalidCastException is just as good as
anything else. Otherwise you get a lot of code bloat for checking for
null unnecessarily.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #6

P: n/a
Jon,

I complely agree with you. There certainly are reasons to cast versus using
"as". However, I believe the reasons are for casting values, which "as" does
not handle.

Otherwise, use "as". It is safer and more efficient at runtime. "As" and
"is" do not perform user-defined conversions. They succeed only if the
runtime type matches the sought type. The never construct a new object to
satisfy a request.

So, if I were to code something like this, I might write:

BusinessType myBusiness = Factory.CreateObject() as BusinessType;
if (myBusiness != null) {
myBusiness.DoStuff();
}

If I were to use the cast, it would look like:

try {
BusinessType yourBusiness = (BusinessType) Factory.CreateObject();
if (yourBusiness != null) {
yourBusiness.DoStuff();
}
}
catch (Exception ex) {
System.Diagnostic.Debug.WriteLine("Exception: " + ex.ToString());
// handle exception
}

So, it is a lot less code when you have to check.

As far as a private array goes, I agree that you could simply cast the
value. But, there is no reason to do this. The "as" is more efficient
because it only checks the runtime types. If they don't match the criteria,
null is returned. And, if you use typed collections like we do, there is no
reason to cast anyway.

But back to the problem described here. This is not a private array. In
point of fact, this is a very public and very variant array. The check is
warrented. We do not know what type of control might be in the Control array
of a particular Cell of a particular Item. This is a classic example of why
to check.

I am not sure what you mean by bloat? (So many people are using that these
days.) Is it the few extra bytes of code I generated? I have already shown
that the "as" is more efficient and requires less code to implement. I know,
I know, your gonna say you could have just said:

BusinessType yourBusiness = (BusinessType) Factory.CreateObject();

or more along the lines of the example you gave:

YourObject yourObject = (YourObject) yourArray[index];

But, the "as" equivalent:

YourObject yourObject = yourArray[index] as YourObject;

is no less efficient than the other version, does not throw (which is really
expensive), and will not attempt to perform user conversions or create a new
object.
BTW: Am I stepping on your turf or someting?

--
Frisky

Intellectuals solve problems; geniuses prevent them. ~ Albert Einstein
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Frisky <Fr***********@NorthPole.net> wrote:
The previous posts are correct and sufficient.

Might I recommend that you use "as" instead of a cast. This is for
converting compatible types. It will only perform reference conversions
and
boxing conversions. The "as" is equivalent to:

expression is type ? (type) expression : (type) null

Note the extra safety in checking the type prior to performing the
conversion. Should the expression in the above not be of the type you are
looking for, it returns null. If you cast like this:

(type) expression

and the type in the expression is not compatible with type, then a
System.InvalidCastException exception will be thrown.


"as" and casting serve slightly different purposes. When it is a
programming error for the value of a variable *not* to be a reference
to a certain type of object, I use a cast. If it's not an error, and I
just want to do something different if it's not an appropriate
reference, that's when as is useful.

For instance, taking values out of a private ArrayList, I'd always use
a cast - if the value isn't of the right type, I've got an error
elsewhere in my code, and an InvalidCastException is just as good as
anything else. Otherwise you get a lot of code bloat for checking for
null unnecessarily.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 17 '05 #7

P: n/a
Jon,

I complely agree with you. There certainly are reasons to cast versus using
"as". However, I believe the reasons are for casting values, which "as" does
not handle.

Otherwise, use "as". It is safer and more efficient at runtime. "As" and
"is" do not perform user-defined conversions. They succeed only if the
runtime type matches the sought type. The never construct a new object to
satisfy a request.

So, if I were to code something like this, I might write:

BusinessType myBusiness = Factory.CreateObject() as BusinessType;
if (myBusiness != null) {
myBusiness.DoStuff();
}

If I were to use the cast, it would look like:

try {
BusinessType yourBusiness = (BusinessType) Factory.CreateObject();
if (yourBusiness != null) {
yourBusiness.DoStuff();
}
}
catch (Exception ex) {
System.Diagnostic.Debug.WriteLine("Exception: " + ex.ToString());
// handle exception
}

So, it is a lot less code when you have to check.

As far as a private array goes, I agree that you could simply cast the
value. But, there is no reason to do this. The "as" is more efficient
because it only checks the runtime types. If they don't match the criteria,
null is returned. And, if you use typed collections like we do, there is no
reason to cast anyway.

But back to the problem described here. This is not a private array. In
point of fact, this is a very public and very variant array. The check is
warrented. We do not know what type of control might be in the Control array
of a particular Cell of a particular Item. This is a classic example of why
to check.

I am not sure what you mean by bloat? (So many people are using that these
days.) Is it the few extra bytes of code I generated? I have already shown
that the "as" is more efficient and requires less code to implement. I know,
I know, your gonna say you could have just said:

BusinessType yourBusiness = (BusinessType) Factory.CreateObject();

or more along the lines of the example you gave:

YourObject yourObject = (YourObject) yourArray[index];

But, the "as" equivalent:

YourObject yourObject = yourArray[index] as YourObject;

is no less efficient than the other version, does not throw (which is really
expensive), and will not attempt to perform user conversions or create a new
object.
BTW: Am I stepping on your turf or someting?

--
Frisky

Intellectuals solve problems; geniuses prevent them. ~ Albert Einstein
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Frisky <Fr***********@NorthPole.net> wrote:
The previous posts are correct and sufficient.

Might I recommend that you use "as" instead of a cast. This is for
converting compatible types. It will only perform reference conversions
and
boxing conversions. The "as" is equivalent to:

expression is type ? (type) expression : (type) null

Note the extra safety in checking the type prior to performing the
conversion. Should the expression in the above not be of the type you are
looking for, it returns null. If you cast like this:

(type) expression

and the type in the expression is not compatible with type, then a
System.InvalidCastException exception will be thrown.


"as" and casting serve slightly different purposes. When it is a
programming error for the value of a variable *not* to be a reference
to a certain type of object, I use a cast. If it's not an error, and I
just want to do something different if it's not an appropriate
reference, that's when as is useful.

For instance, taking values out of a private ArrayList, I'd always use
a cast - if the value isn't of the right type, I've got an error
elsewhere in my code, and an InvalidCastException is just as good as
anything else. Otherwise you get a lot of code bloat for checking for
null unnecessarily.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 17 '05 #8

P: n/a
Frisky <Fr***********@NorthPole.net> wrote:
I complely agree with you. There certainly are reasons to cast versus using
"as". However, I believe the reasons are for casting values, which "as" does
not handle.

Otherwise, use "as". It is safer and more efficient at runtime. "As" and
"is" do not perform user-defined conversions. They succeed only if the
runtime type matches the sought type. The never construct a new object to
satisfy a request.

So, if I were to code something like this, I might write:

BusinessType myBusiness = Factory.CreateObject() as BusinessType;
if (myBusiness != null) {
myBusiness.DoStuff();
}

If I were to use the cast, it would look like:

try {
BusinessType yourBusiness = (BusinessType) Factory.CreateObject();
if (yourBusiness != null) {
yourBusiness.DoStuff();
}
}
catch (Exception ex) {
System.Diagnostic.Debug.WriteLine("Exception: " + ex.ToString());
// handle exception
}

So, it is a lot less code when you have to check.
You should almost never *actually* catch exceptions at the point
they're generated. They should bubble up.

Any proper factory that's asked to create an object should either throw
an exception or create the appropriate object. If it's returning
something other than the appropriate type I'm expecting, I almost
certainly want an exception. I'd write your code as:

BusinessType yourBusiness = (BusinessType) Factory.CreateObject();

I don't see the problem.
As far as a private array goes, I agree that you could simply cast the
value. But, there is no reason to do this. The "as" is more efficient
because it only checks the runtime types. If they don't match the criteria,
null is returned. And, if you use typed collections like we do, there is no
reason to cast anyway.
Casting and "as" are equally efficient when there aren't conversions
involved, and that's decided at compile-time, not runtime.
But back to the problem described here. This is not a private array. In
point of fact, this is a very public and very variant array. The check is
warrented. We do not know what type of control might be in the Control array
of a particular Cell of a particular Item. This is a classic example of why
to check.
If you genuinely don't know *and* you want to handle the situation
where the result isn't a TextBox, sure. I would probably just throw an
exception there anyway though, in most cases.
I am not sure what you mean by bloat? (So many people are using that these
days.) Is it the few extra bytes of code I generated? I have already shown
that the "as" is more efficient and requires less code to implement.
No, because you're checking for null manually rather than letting the
cast do the check for you and throw the exception appropriately. The
important part of the bloat here is the source bloat - the extra check
takes up precious space that could be getting on with what you actually
want to be doing. That's the joy of using exceptions rather than return
values - most of your actual code gets on with what you want to do,
rather than error checking.
I know,
I know, your gonna say you could have just said:

BusinessType yourBusiness = (BusinessType) Factory.CreateObject();

or more along the lines of the example you gave:

YourObject yourObject = (YourObject) yourArray[index];
ArrayList, actually. If you've got an actual array, I'd expect it to be
the right type to start with.
But, the "as" equivalent:

YourObject yourObject = yourArray[index] as YourObject;

is no less efficient than the other version, does not throw (which is really
expensive), and will not attempt to perform user conversions or create a new
object.
But I almost always *want* it to throw - and to get the "as" version to
throw, you have to put more code in.

As for user conversions - as I said before, that's decided at compile-
time, not run-time, so there's no bloat there, and the only times they
*would* be used would be when I'd want them anyway. No new objects will
be created when conversions aren't invoked.
BTW: Am I stepping on your turf or someting?


Not at all. I just happen to disagree with you on code style.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #9

P: n/a
Intellectuals solve problems; geniuses prevent them. ~ Albert Einstein
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Frisky <Fr***********@NorthPole.net> wrote:
I complely agree with you. There certainly are reasons to cast versus
using
"as". However, I believe the reasons are for casting values, which "as"
does
not handle.

Otherwise, use "as". It is safer and more efficient at runtime. "As" and
"is" do not perform user-defined conversions. They succeed only if the
runtime type matches the sought type. The never construct a new object to
satisfy a request.

So, if I were to code something like this, I might write:

BusinessType myBusiness = Factory.CreateObject() as BusinessType;
if (myBusiness != null) {
myBusiness.DoStuff();
}

If I were to use the cast, it would look like:

try {
BusinessType yourBusiness = (BusinessType) Factory.CreateObject();
if (yourBusiness != null) {
yourBusiness.DoStuff();
}
}
catch (Exception ex) {
System.Diagnostic.Debug.WriteLine("Exception: " + ex.ToString());
// handle exception
}

So, it is a lot less code when you have to check.
You should almost never *actually* catch exceptions at the point
they're generated. They should bubble up.

Any proper factory that's asked to create an object should either throw
an exception or create the appropriate object. If it's returning
something other than the appropriate type I'm expecting, I almost
certainly want an exception. I'd write your code as:

BusinessType yourBusiness = (BusinessType) Factory.CreateObject();

I don't see the problem.


<grin>Like I said you would say. (See below)</grin>

Stick to the point. You should use "as" not casts whereever possible. Where
your catch does not change which you should use.

But, if you would like to save yourself all of the exception processing, a
simple check for null will do the trick. You code will be faster, and you
won't have to find another place to hide some exception code. You have
prevented the problem prior to it occurring.

In most instances, the exception, which must eventually be caught, will end
up doing nothing. By bubbling the throw up, I just skipped the rest of the
code in that method. So, if the rest of the code would have run, it won't
now. This may be what you wanted, but with the null check you can do either.
And the null check costs virtually nothing.
As far as a private array goes, I agree that you could simply cast the
value. But, there is no reason to do this. The "as" is more efficient
because it only checks the runtime types. If they don't match the
criteria,
null is returned. And, if you use typed collections like we do, there is
no
reason to cast anyway.


Casting and "as" are equally efficient when there aren't conversions
involved, and that's decided at compile-time, not runtime.


Are you conceeding my point? So, "as" and cast are equivalent in the worst
case, and "as" is faster in the best case. Like I said, always use "as"
unless you can't.

The code example given is most definitley a runtime type check. There is
know way the compiler can possibly know if the type of an item placed in the
control array is a particular control. It only knows that it "is a" Control.
This check and possible exception are generated at runtime.

(Check out the article http://www.codeproject.com/csharp/csharpcasts.asp)
While I have not verified his results, my results were similar.
But back to the problem described here. This is not a private array. In
point of fact, this is a very public and very variant array. The check is
warrented. We do not know what type of control might be in the Control
array
of a particular Cell of a particular Item. This is a classic example of
why
to check.


If you genuinely don't know *and* you want to handle the situation
where the result isn't a TextBox, sure. I would probably just throw an
exception there anyway though, in most cases.


There is nothing here that says you should not use "as". Again, as you
stated above, it is at least as efficient in the worst case. Oh, and if you
don't check for null, it will still throw. But see below for why you might
not want to do that.
I am not sure what you mean by bloat? (So many people are using that
these
days.) Is it the few extra bytes of code I generated? I have already
shown
that the "as" is more efficient and requires less code to implement.


No, because you're checking for null manually rather than letting the
cast do the check for you and throw the exception appropriately. The
important part of the bloat here is the source bloat - the extra check
takes up precious space that could be getting on with what you actually
want to be doing. That's the joy of using exceptions rather than return
values - most of your actual code gets on with what you want to do,
rather than error checking.


Well, this of course depends on how you write your code. If you don't mind
poor performance, throw all over the place. The combined "as" and null check
are still way less impact to your code that the cast. And, when you do
throw, the cost is huge.
I know,
I know, your gonna say you could have just said:

BusinessType yourBusiness = (BusinessType) Factory.CreateObject();

or more along the lines of the example you gave:

YourObject yourObject = (YourObject) yourArray[index];


ArrayList, actually. If you've got an actual array, I'd expect it to be
the right type to start with.


First, I do not know how you would know, based on the code here, exactly how
this array was implemented. And if it was trully an array, what type it was
defined on. An array does not have to be of your particular type. It might
be of a base type or object type.

And yes, it works with ArrayList, HashTables, etc. too.
But, the "as" equivalent:

YourObject yourObject = yourArray[index] as YourObject;

is no less efficient than the other version, does not throw (which is
really
expensive), and will not attempt to perform user conversions or create a
new
object.


But I almost always *want* it to throw - and to get the "as" version to
throw, you have to put more code in.

As for user conversions - as I said before, that's decided at compile-
time, not run-time, so there's no bloat there, and the only times they
*would* be used would be when I'd want them anyway. No new objects will
be created when conversions aren't invoked.


First, here is fundamental difference. I *don't want* to throw. If I am
going to throw, I know there is a *huge* overhead. I need to be judicious
and make sure that throwing is correct for this particular problem.
Validating UI objects should almost always involve checking and not throwing
because of performance. Also, again, I can continue with other updates to
the UI even if this one control is not behaving.

Second, there is no more code required to throw. When the "as" is performed,
if it fails, you get null. If you attempt to use the null, as in the long
string of code originally shown, you will most certainly throw an exception.

I don't know how you would know based on the code shown if a user conversion
exists or not. Are you saying because we havn't shown one. I have seen this
assumption bite many people. But, again, check out the article, and perform
your own tests. I am not worried about bloat, but performance.

I don't think either of these methods bloats the code. One is just faster
than the other. (Not bloat; performance) And the slower casting method does
not afford me any value add.
BTW: Am I stepping on your turf or someting?


Not at all. I just happen to disagree with you on code style.


Just though I would ask. And, actually, the reason I asked is because of the
reason you stated. You have disagreed with everything I wrote. But, I have
noticed similar commnents in other articles in this group, which you
ignored. ???

I certainly do not mind that you and I going back and forth. This is
healthy, and both of us stand to learn something. Right?

However, I would perfer a more contructive approach. A cooperative attitude
would be nice. Even if you don't like my code style. I like it a lot. And I
respect yours.
--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 17 '05 #10

P: n/a
Frisky <Fr***********@NorthPole.net> wrote:
BusinessType yourBusiness = (BusinessType) Factory.CreateObject();

I don't see the problem.
<grin>Like I said you would say. (See below)</grin>

Stick to the point. You should use "as" not casts whereever possible. Where
your catch does not change which you should use.


Yes it does. It makes a huge difference to the code. When you use as
and test for nullity, you have to have that check *everywhere*. You
gave sample code which mimicked that, but catching the exception - and
unsurprisingly, it came out looking nasty. Change that to catching
exceptions centrally, and you end up with *much* cleaner code.
But, if you would like to save yourself all of the exception processing, a
simple check for null will do the trick. You code will be faster, and you
won't have to find another place to hide some exception code. You have
prevented the problem prior to it occurring.
No, you haven't prevented the problem - you've just decided to
understand the problem manually rather than automatically. I don't
believe the code will be faster, either - why would it be? Both are
doing the same thing, asking the runtime to do an "as" and then
checking for nullity. (That's what a cast does internally.)
In most instances, the exception, which must eventually be caught, will end
up doing nothing. By bubbling the throw up, I just skipped the rest of the
code in that method. So, if the rest of the code would have run, it won't
now. This may be what you wanted, but with the null check you can do either.
And the null check costs virtually nothing.
*If* you want the code to do nothing, yes, you should use "as". I find
that case is much, much rarer than the case where you know that if
there's an unexpected type there, it's due to a programming error, and
you want to stop what you're doing as soon as possible.
Casting and "as" are equally efficient when there aren't conversions
involved, and that's decided at compile-time, not runtime.


Are you conceeding my point?


Not at all.
So, "as" and cast are equivalent in the worst case, and "as" is
faster in the best case.
In your best case, the operations are entirely distinct - they do
different things. In your worst case, they're equivalent, and yet you
claim above that it's faster.
Like I said, always use "as" unless you can't.
If you like doing all your error handling manually - I don't.
The code example given is most definitley a runtime type check. There is
know way the compiler can possibly know if the type of an item placed in the
control array is a particular control. It only knows that it "is a" Control.
This check and possible exception are generated at runtime.
I don't think you read my post carefully enough. The compiler decides
at compile-time whether or not it's just a cast, or whether it's a
user-defined conversion.
(Check out the article http://www.codeproject.com/csharp/csharpcasts.asp)
While I have not verified his results, my results were similar.
I'll try it some time. Not that I believe the performance difference is
ever going to be significant in many real applications - whereas the
cost of failing to check for nullity *could* be significant, and all
too easy to miss.
If you genuinely don't know *and* you want to handle the situation
where the result isn't a TextBox, sure. I would probably just throw an
exception there anyway though, in most cases.


There is nothing here that says you should not use "as".


No, but there's nothing to say you shouldn't use a cast either - and
the difference is between:

TextBox tb = (TextBox) control;

and:

TextBox tb = control as TextBox;
if (tb==null)
{
throw new SomeOtherException();
}

Do you really find the second code clearer?
Again, as you
stated above, it is at least as efficient in the worst case. Oh, and if you
don't check for null, it will still throw. But see below for why you might
not want to do that.
It will only throw in situations where you immediately use it though -
which isn't always the case. What if you then pass it into a method
which happily accepts nulls, but treats them differently? Very subtle
bugs can be introduced that way...
No, because you're checking for null manually rather than letting the
cast do the check for you and throw the exception appropriately. The
important part of the bloat here is the source bloat - the extra check
takes up precious space that could be getting on with what you actually
want to be doing. That's the joy of using exceptions rather than return
values - most of your actual code gets on with what you want to do,
rather than error checking.


Well, this of course depends on how you write your code. If you don't mind
poor performance, throw all over the place. The combined "as" and null check
are still way less impact to your code that the cast. And, when you do
throw, the cost is huge.


It's not huge. It's about 100,000th of a second on my (not top of the
range) laptop. That's not huge unless you're doing it time and time
again, which indicates other problems in your code.

I *do* throw all over the place - pretty much whenever I detect an
error condition. Does the performance get hit? No, because there rarely
*is* an error condition, and if there is, there's the hit of *one*
exception, rather than hundreds of thousands. Like I've said,
exceptions costing real life performance is more of a myth than reality
in almost all applications.
ArrayList, actually. If you've got an actual array, I'd expect it to be
the right type to start with.


First, I do not know how you would know, based on the code here, exactly how
this array was implemented. And if it was trully an array, what type it was
defined on. An array does not have to be of your particular type. It might
be of a base type or object type.


Usually when I'm dealing with arrays, they're member variables of my
own class, and they're usually of the right type. I rarely have to cast
from arrays.

<snip>
As for user conversions - as I said before, that's decided at compile-
time, not run-time, so there's no bloat there, and the only times they
*would* be used would be when I'd want them anyway. No new objects will
be created when conversions aren't invoked.


First, here is fundamental difference. I *don't want* to throw. If I am
going to throw, I know there is a *huge* overhead.


Well, there's a ~0.001ms overhead. I don't think that's huge, unless
you're planning to do it thousands of times - which basically isn't
going to happen here.
I need to be judicious
and make sure that throwing is correct for this particular problem.
Validating UI objects should almost always involve checking and not throwing
because of performance. Also, again, I can continue with other updates to
the UI even if this one control is not behaving.
Validating UI *input* should almost always involve checking (although
not so much for performance reasons - a human in front of a UI
certainly can't hit keys or move the mouse quickly enough to make it a
problem to throw an exception every time they do so). Validating
whether a control is actually what it should be? That doesn't need
checking manually. If it's wrong, the code itself is screwed up.
Second, there is no more code required to throw. When the "as" is performed,
if it fails, you get null. If you attempt to use the null, as in the long
string of code originally shown, you will most certainly throw an exception.
In this particular case - what about when you're passing it elsewhere,
or not using it immediately?
I don't know how you would know based on the code shown if a user conversion
exists or not.
Because there's no defined conversion between Control and TextBox.
Operators are overloaded, not overridden - it's a compile-time thing,
not a run-time thing. If the actual control were some third-party
control which didn't inherit from TextBox, but had a user-defined
conversion to it, that wouldn't be performed in the casting case,
because the compiler doesn't know about it at compile-time.
Are you saying because we havn't shown one. I have seen this
assumption bite many people. But, again, check out the article, and perform
your own tests. I am not worried about bloat, but performance.
I believe you are artificially worried about performance, perhaps
partly based on previous bad experiences of very odd situations such as
the one you mentioned where you didn't know what resources were in an
assembly. (Any reason not to find them out using
GetManifestResourceNames? Better than asking speculatively in that
situation, I'd say.)
I don't think either of these methods bloats the code. One is just faster
than the other. (Not bloat; performance) And the slower casting method does
not afford me any value add.
Whereas it gives me the following benefits:
1) Shorter code where the main success path is clearer, not hidden by
potential errors which can be handled (by throwing) by the runtime

2) Less room for accidentally forgetting the nullity check.
BTW: Am I stepping on your turf or someting?


Not at all. I just happen to disagree with you on code style.


Just though I would ask. And, actually, the reason I asked is because of the
reason you stated. You have disagreed with everything I wrote. But, I have
noticed similar commnents in other articles in this group, which you
ignored. ???


I don't respond to every article which I might disagree with - there
wouldn't be time. You'll find I *do* tend to respond to people who
claim there's a "huge overhead" in throwing exceptions though - they
tend not to understand that exceptions can be thrown tens to hundreds
of thousands of times per second in release mode (which is where
performance matters). Once again, the actual cost of throwing an
exception is almost *never* a bottleneck in real applications. Failure
to check a return value is very easy to do though - and I'd always
rather have a slight performance hit than a bug.
I certainly do not mind that you and I going back and forth. This is
healthy, and both of us stand to learn something. Right?
Absolutely.
However, I would perfer a more contructive approach. A cooperative attitude
would be nice. Even if you don't like my code style. I like it a lot. And I
respect yours.


I don't think I've been any less respectful to you than you have to me.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #11

P: n/a
Frisky <Fr***********@NorthPole.net> wrote:

<snip>
(Check out the article http://www.codeproject.com/csharp/csharpcasts.asp)
While I have not verified his results, my results were similar.


The graph on that page bothered me, so I tried my own test. I normally
got results which were within about 5% of each other - sometimes one
approach being faster, sometimes the other. Nothing significant, in
other words.

I couldn't reproduce the results he had unless I also didn't have a
nullity test - in which case you're comparing a non-error-checking
solution with an error-checking solution.

If your natural reaction is to say, "Ah, but as soon as you use the
reference" you need to then check what happens when you *do* use the
reference - and the answer is that the automatic nullity check which
happens there takes just as long as the casting in the first place. The
JIT is smart enough to know that if a local variable was null earlier
and isn't changed in between then and now, then it's not going to be
null now.

In other words, the only situation in which I can provoke the factor of
6 or so performance increase using "as" over casting is when you then
don't use the reference for a method call. I suppose in some
situations, when you're passing the local variable's value as a
parameter to another method, that might actually occur. I venture to
suggest that the number of times it's actually significant in the real
world is pretty close to zero.

In other words, I see no evidence that any choice regarding the use of
"as" vs casting should be made on performance grounds. If you still
think that performance is an issue, perhaps you could come up with a
real world scenario where it's significant.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #12

P: n/a
Intellectuals solve problems; geniuses prevent them. ~ Albert Einstein
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Frisky <Fr***********@NorthPole.net> wrote:
> BusinessType yourBusiness = (BusinessType) Factory.CreateObject();
>
> I don't see the problem.
<grin>Like I said you would say. (See below)</grin>

Stick to the point. You should use "as" not casts whereever possible.
Where
your catch does not change which you should use.


Yes it does. It makes a huge difference to the code. When you use as
and test for nullity, you have to have that check *everywhere*. You
gave sample code which mimicked that, but catching the exception - and
unsurprisingly, it came out looking nasty. Change that to catching
exceptions centrally, and you end up with *much* cleaner code.


I'm not getting huge difference; unless you mean how fast my code is, and
how easy to read it is, etc. :)

I don't have to check for nulls at all. If I don't it will still be at least
as fast or faster, and I will still throw.

But, if I do check for null, I don't have to check everywhere. I only have
to check where it counts. And I should be judicuous in this.

There is nothing nasty about that code using "as". Its short, easy to read,
and easy to understand. Actually, the code I showed made the example for
exceptions look ugly; in case in point where you do have to catch.

Also, you can't bubble everything up. Nor should you. The right object with
that responsibility should handle the exceptions he is responsible for.
Sometimes that means bubbling things up. Sometimes it means stop and pay
attention.

If you are refering to the single line of code that simply throws when
something goes wrong, I don't necessarily call that better. It comes at the
cost of increased complexity. I have now deferred that error to somewhere
else. But where? And, in how many places?
But, if you would like to save yourself all of the exception processing,
a
simple check for null will do the trick. You code will be faster, and you
won't have to find another place to hide some exception code. You have
prevented the problem prior to it occurring.


No, you haven't prevented the problem - you've just decided to
understand the problem manually rather than automatically. I don't
believe the code will be faster, either - why would it be? Both are
doing the same thing, asking the runtime to do an "as" and then
checking for nullity. (That's what a cast does internally.)


No, really I have decided to ignore the condition as not being a problem.
Just skip this code if its not relevant.

And the code will be faster. If you have a GUI that is firing tons of
exceptions, and those exceptions fire yet more messages, that guess what,
fire more exceptions, pretty soon you will be sucking wind.

If you look at the execution time, even the check alone (agreeably over very
large numbers) is serveral orders faster. And both will throw if you do not
check for null. Speaking distinctly as a comparison of casting to "as". But
if you don't throw, you just ignore, there is nothing left to do, no stack
to grab information on, no memory variables to create.
In most instances, the exception, which must eventually be caught, will
end
up doing nothing. By bubbling the throw up, I just skipped the rest of
the
code in that method. So, if the rest of the code would have run, it won't
now. This may be what you wanted, but with the null check you can do
either.
And the null check costs virtually nothing.


*If* you want the code to do nothing, yes, you should use "as". I find
that case is much, much rarer than the case where you know that if
there's an unexpected type there, it's due to a programming error, and
you want to stop what you're doing as soon as possible.


But "as" is at least as fast, or faster than a cast. So, unless you mean to
cast, to get user conversions, or you have a value type, why used it? The
"as" is the straight up performance winner.
> Casting and "as" are equally efficient when there aren't conversions
> involved, and that's decided at compile-time, not runtime.


Are you conceeding my point?


Not at all.


But you just said, "as" is equally fast in the worst case. In all other
cases, its faster. Did you look at that article on Code Project?
So, "as" and cast are equivalent in the worst case, and "as" is
faster in the best case.


In your best case, the operations are entirely distinct - they do
different things. In your worst case, they're equivalent, and yet you
claim above that it's faster.


And it is.
Like I said, always use "as" unless you can't.


If you like doing all your error handling manually - I don't.


You can still use exceptions.
The code example given is most definitley a runtime type check. There is
know way the compiler can possibly know if the type of an item placed in
the
control array is a particular control. It only knows that it "is a"
Control.
This check and possible exception are generated at runtime.


I don't think you read my post carefully enough. The compiler decides
at compile-time whether or not it's just a cast, or whether it's a
user-defined conversion.
(Check out the article http://www.codeproject.com/csharp/csharpcasts.asp)
While I have not verified his results, my results were similar.


I'll try it some time. Not that I believe the performance difference is
ever going to be significant in many real applications - whereas the
cost of failing to check for nullity *could* be significant, and all
too easy to miss.


And while you may not find that the performance will pay off, it is better
to stick with high performance as a rule if you can.

And, I'm not saying you have to check for null if you use "as". You can
still stick with your current exception strategy.
> If you genuinely don't know *and* you want to handle the situation
> where the result isn't a TextBox, sure. I would probably just throw an
> exception there anyway though, in most cases.


There is nothing here that says you should not use "as".


No, but there's nothing to say you shouldn't use a cast either - and
the difference is between:

TextBox tb = (TextBox) control;

and:

TextBox tb = control as TextBox;
if (tb==null)
{
throw new SomeOtherException();
}

Do you really find the second code clearer?


Comparing Apples to Apples:

TextBox tb = (TextBox) control;

and:

TextBox tb = control as TextBox;

I find them equally readable.
Again, as you
stated above, it is at least as efficient in the worst case. Oh, and if
you
don't check for null, it will still throw. But see below for why you
might
not want to do that.


It will only throw in situations where you immediately use it though -
which isn't always the case. What if you then pass it into a method
which happily accepts nulls, but treats them differently? Very subtle
bugs can be introduced that way...


I am not sure what you mean by this. ???

I only check for null where null values are not allowed. If a function takes
an object type, but does not allow nulls, it would assert. The code
provifing the null value would be in error.
> No, because you're checking for null manually rather than letting the
> cast do the check for you and throw the exception appropriately. The
> important part of the bloat here is the source bloat - the extra check
> takes up precious space that could be getting on with what you actually
> want to be doing. That's the joy of using exceptions rather than return
> values - most of your actual code gets on with what you want to do,
> rather than error checking.


Well, this of course depends on how you write your code. If you don't
mind
poor performance, throw all over the place. The combined "as" and null
check
are still way less impact to your code that the cast. And, when you do
throw, the cost is huge.


It's not huge. It's about 100,000th of a second on my (not top of the
range) laptop. That's not huge unless you're doing it time and time
again, which indicates other problems in your code.


Or, you rely on lots of reentrant code, or are handling large quantities of
business rules and data, or etc. And performance overall does matter to me.
I would rather set me design goals based on using the faster of two options
unless there is a compelling reason not to. I see no compelling reason to
use a cast over "as". In light of that, I see performance as a compelling
reason to use "as" over a cast.

I simply add that even with the null check included, it is still faster than
the cast. Not that you have to do it that way. You can stick with your own
exception strategy.
I *do* throw all over the place - pretty much whenever I detect an
error condition. Does the performance get hit? No, because there rarely
*is* an error condition, and if there is, there's the hit of *one*
exception, rather than hundreds of thousands. Like I've said,
exceptions costing real life performance is more of a myth than reality
in almost all applications.
Ok, now you are speaking my language. But, I thought I had said this in the
beinning anyway. It depends, are you expecting to throw, or are you
expecting not to throw.

And in general, my design is based on the approach you describe here. If you
never have an error, youv'e won the battle before it started.
> ArrayList, actually. If you've got an actual array, I'd expect it to be
> the right type to start with.


First, I do not know how you would know, based on the code here, exactly
how
this array was implemented. And if it was trully an array, what type it
was
defined on. An array does not have to be of your particular type. It
might
be of a base type or object type.


Usually when I'm dealing with arrays, they're member variables of my
own class, and they're usually of the right type. I rarely have to cast
from arrays.


I use inheritence a lot. My arrays are not always so clean cut. But, if you
don't need to cast, you don't need "as" either.
<snip>
> As for user conversions - as I said before, that's decided at compile-
> time, not run-time, so there's no bloat there, and the only times they
> *would* be used would be when I'd want them anyway. No new objects will
> be created when conversions aren't invoked.
First, here is fundamental difference. I *don't want* to throw. If I am
going to throw, I know there is a *huge* overhead.


Well, there's a ~0.001ms overhead. I don't think that's huge, unless
you're planning to do it thousands of times - which basically isn't
going to happen here.


For a single instruction on a 3.0 Ghz box that's huge. At that rate, I would
only be able to execute 1000 instuctions a second. But, my tests indicated
it was a higher hit than that.
I need to be judicious
and make sure that throwing is correct for this particular problem.
Validating UI objects should almost always involve checking and not
throwing
because of performance. Also, again, I can continue with other updates to
the UI even if this one control is not behaving.


Validating UI *input* should almost always involve checking (although
not so much for performance reasons - a human in front of a UI
certainly can't hit keys or move the mouse quickly enough to make it a
problem to throw an exception every time they do so). Validating
whether a control is actually what it should be? That doesn't need
checking manually. If it's wrong, the code itself is screwed up.


Well that depends. We usually build dynamic screens. And, the users can drag
and drop UI components from one panel to the other. We mimic a lot of what
VS 2003 does but for our application.
Second, there is no more code required to throw. When the "as" is
performed,
if it fails, you get null. If you attempt to use the null, as in the long
string of code originally shown, you will most certainly throw an
exception.


In this particular case - what about when you're passing it elsewhere,
or not using it immediately?


Depends on the elsewhere. But I don't tend to get values here for use
elsewhere. Unless elsewhere is another responsibility, but then again, if
its not responsible, that must make me, so I would need to do the
validation.
I don't know how you would know based on the code shown if a user
conversion
exists or not.


Because there's no defined conversion between Control and TextBox.
Operators are overloaded, not overridden - it's a compile-time thing,
not a run-time thing. If the actual control were some third-party
control which didn't inherit from TextBox, but had a user-defined
conversion to it, that wouldn't be performed in the casting case,
because the compiler doesn't know about it at compile-time.


Quite. True, our code is down-casting our special textbox classes to one of
the classes in its lineage.

public static implicit operator TextBox(SuperDuperTextBox control)
{
// conversion code
}
Are you saying because we havn't shown one. I have seen this
assumption bite many people. But, again, check out the article, and
perform
your own tests. I am not worried about bloat, but performance.


I believe you are artificially worried about performance, perhaps
partly based on previous bad experiences of very odd situations such as
the one you mentioned where you didn't know what resources were in an
assembly. (Any reason not to find them out using
GetManifestResourceNames? Better than asking speculatively in that
situation, I'd say.)


I wish it had been that easy. But, performance if not artificial. And, the
systems I have written do not suffer from these issues. Sure, I base the
things I do on history. Experience has been a great teacher for me. Hence my
points.
I don't think either of these methods bloats the code. One is just faster
than the other. (Not bloat; performance) And the slower casting method
does
not afford me any value add.


Whereas it gives me the following benefits:
1) Shorter code where the main success path is clearer, not hidden by
potential errors which can be handled (by throwing) by the runtime

2) Less room for accidentally forgetting the nullity check.


The code is not any shorter or longer. Cast versus "as". Not anymore clear.
In fact, hidden exception handling is who knows where. Its more comlpe.

Did you forget? I thought you wanted to throw? :) This is no different than
forgetting to add the hanlder code. Or anything else for that matter. You do
step through your code in the debugger when you write it don't you?
>> BTW: Am I stepping on your turf or someting?
>
> Not at all. I just happen to disagree with you on code style.


Just though I would ask. And, actually, the reason I asked is because of
the
reason you stated. You have disagreed with everything I wrote. But, I
have
noticed similar commnents in other articles in this group, which you
ignored. ???


I don't respond to every article which I might disagree with - there
wouldn't be time. You'll find I *do* tend to respond to people who
claim there's a "huge overhead" in throwing exceptions though - they
tend not to understand that exceptions can be thrown tens to hundreds
of thousands of times per second in release mode (which is where
performance matters). Once again, the actual cost of throwing an
exception is almost *never* a bottleneck in real applications. Failure
to check a return value is very easy to do though - and I'd always
rather have a slight performance hit than a bug.
I certainly do not mind that you and I going back and forth. This is
healthy, and both of us stand to learn something. Right?


Absolutely.
However, I would perfer a more contructive approach. A cooperative
attitude
would be nice. Even if you don't like my code style. I like it a lot. And
I
respect yours.


I don't think I've been any less respectful to you than you have to me.


Not disrespect. I just found that you took exception (no pun intended) to my
comments in several post, yet steered clear of others. I just wondered if
you had something against me, or if you were after interllectual discussion.

You do seem adamant. But then again, so do I. :)

--
Frisky
--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 17 '05 #13

P: n/a
Frisky <Fr***********@NorthPole.net> wrote:
Yes it does. It makes a huge difference to the code. When you use as
and test for nullity, you have to have that check *everywhere*. You
gave sample code which mimicked that, but catching the exception - and
unsurprisingly, it came out looking nasty. Change that to catching
exceptions centrally, and you end up with *much* cleaner code.
I'm not getting huge difference; unless you mean how fast my code is, and
how easy to read it is, etc. :)


We clearly have different ideas about readability. For me, making it
very easy to see the intended usual code path makes things more
readable than interspersing that with checking return values.
I don't have to check for nulls at all. If I don't it will still be at least
as fast or faster, and I will still throw.
You'll still throw *sometimes*. Not always. It depends how you use the
variable.
But, if I do check for null, I don't have to check everywhere. I only have
to check where it counts. And I should be judicuous in this.
Yup - you have to get it right, otherwise you could easily introduce a
bug. I prefer to let the runtime make the choice.
There is nothing nasty about that code using "as". Its short, easy to read,
and easy to understand. Actually, the code I showed made the example for
exceptions look ugly; in case in point where you do have to catch.
Which is very rare - you deliberately showed the worst possible case
for casting, and you're now asking me to compare that with the best
possible case for using "as" (where you don't even have to check the
result).
Also, you can't bubble everything up. Nor should you. The right object with
that responsibility should handle the exceptions he is responsible for.
Sometimes that means bubbling things up. Sometimes it means stop and pay
attention.

If you are refering to the single line of code that simply throws when
something goes wrong, I don't necessarily call that better. It comes at the
cost of increased complexity. I have now deferred that error to somewhere
else. But where? And, in how many places?
Almost everywhere. Exceptions should usually be thrown when something
truly unexpected has happened - *especially* in the case of casting. If
there *is* a reasonable chance that the cast would fail (eg if you've
loaded a type whose name has been provided by the user) then that *is*
a good place to use "as" instead.
No, you haven't prevented the problem - you've just decided to
understand the problem manually rather than automatically. I don't
believe the code will be faster, either - why would it be? Both are
doing the same thing, asking the runtime to do an "as" and then
checking for nullity. (That's what a cast does internally.)


No, really I have decided to ignore the condition as not being a problem.
Just skip this code if its not relevant.

And the code will be faster. If you have a GUI that is firing tons of
exceptions, and those exceptions fire yet more messages, that guess what,
fire more exceptions, pretty soon you will be sucking wind.


But that just doesn't happen in reality. Unless you've got your code
hooked up very badly, you shouldn't be firing tons of exceptions
anyway. I've *never* suggested that exceptions should be thrown often
in terms of actual running code, just in terms of places in the code.
If you look at the execution time, even the check alone (agreeably over very
large numbers) is serveral orders faster. And both will throw if you do not
check for null. Speaking distinctly as a comparison of casting to "as". But
if you don't throw, you just ignore, there is nothing left to do, no stack
to grab information on, no memory variables to create.
No, "as" won't throw if you check for null and then use the value
somewhere that null is a valid value, but possibly not the one that you
actually want.
*If* you want the code to do nothing, yes, you should use "as". I find
that case is much, much rarer than the case where you know that if
there's an unexpected type there, it's due to a programming error, and
you want to stop what you're doing as soon as possible.


But "as" is at least as fast, or faster than a cast. So, unless you mean to
cast, to get user conversions, or you have a value type, why used it? The
"as" is the straight up performance winner.


No, it's the performance equal unless you decide not to check it, at
which point I believe it's a bug trap, deferring the point at which you
find out something has gone wrong.
Not at all.


But you just said, "as" is equally fast in the worst case. In all other
cases, its faster. Did you look at that article on Code Project?


Yes. I actually *tried* it though. That article on Code Project left
out a lot of stuff (like code). Basically, unless you're using the
value from "as" in such a way that it *doesn't* show up errors
reasonably quickly, there's no real performance difference.
In your best case, the operations are entirely distinct - they do
different things. In your worst case, they're equivalent, and yet you
claim above that it's faster.


And it is.


Only if you don't check the value.
Like I said, always use "as" unless you can't.


If you like doing all your error handling manually - I don't.


You can still use exceptions.


And I will!
(Check out the article http://www.codeproject.com/csharp/csharpcasts.asp)
While I have not verified his results, my results were similar.


I'll try it some time. Not that I believe the performance difference is
ever going to be significant in many real applications - whereas the
cost of failing to check for nullity *could* be significant, and all
too easy to miss.


And while you may not find that the performance will pay off, it is better
to stick with high performance as a rule if you can.


Knuth disagrees.
And, I'm not saying you have to check for null if you use "as". You can
still stick with your current exception strategy.
But to get the exception, you have to check for null or risk making the
eventual error harder to understand.
No, but there's nothing to say you shouldn't use a cast either - and
the difference is between:

TextBox tb = (TextBox) control;

and:

TextBox tb = control as TextBox;
if (tb==null)
{
throw new SomeOtherException();
}

Do you really find the second code clearer?


Comparing Apples to Apples:

TextBox tb = (TextBox) control;

and:

TextBox tb = control as TextBox;

I find them equally readable.


So do I - but the latter will mask any errors until later, unless you
have the check.
It will only throw in situations where you immediately use it though -
which isn't always the case. What if you then pass it into a method
which happily accepts nulls, but treats them differently? Very subtle
bugs can be introduced that way...


I am not sure what you mean by this. ???

I only check for null where null values are not allowed. If a function takes
an object type, but does not allow nulls, it would assert. The code
provifing the null value would be in error.


But null could be an acceptable value for the method call, but one
which you (as the caller) never want to provide in this case. You also
lose the ability to distinguish between the original value being null
(which may be valid) and the original value being a reference to an
object of the wrong type.
It's not huge. It's about 100,000th of a second on my (not top of the
range) laptop. That's not huge unless you're doing it time and time
again, which indicates other problems in your code.


Or, you rely on lots of reentrant code, or are handling large quantities of
business rules and data, or etc. And performance overall does matter to me.
I would rather set me design goals based on using the faster of two options
unless there is a compelling reason not to. I see no compelling reason to
use a cast over "as". In light of that, I see performance as a compelling
reason to use "as" over a cast.


Then we fundamentally disagree on what constitutes significant
performance. I believe that universally choosing "as" for performance
reasons when it *can* introduce bugs is a *really* bad idea.
I simply add that even with the null check included, it is still faster than
the cast. Not that you have to do it that way. You can stick with your own
exception strategy.
With the null check included, they're effectively the same speed in my
tests. Sometimes one version runs faster, sometimes the other.
I *do* throw all over the place - pretty much whenever I detect an
error condition. Does the performance get hit? No, because there rarely
*is* an error condition, and if there is, there's the hit of *one*
exception, rather than hundreds of thousands. Like I've said,
exceptions costing real life performance is more of a myth than reality
in almost all applications.


Ok, now you are speaking my language. But, I thought I had said this in the
beinning anyway. It depends, are you expecting to throw, or are you
expecting not to throw.


And I almost always want to throw in the very rare situation that I've
got an object of an unexpected type.
And in general, my design is based on the approach you describe here. If you
never have an error, youv'e won the battle before it started.
Indeed. And if you *do* have an error, chances are you're not going to
get to the same situation thousands of times, and the performance hit
will be absolutely tiny.
Usually when I'm dealing with arrays, they're member variables of my
own class, and they're usually of the right type. I rarely have to cast
from arrays.


I use inheritence a lot. My arrays are not always so clean cut. But, if you
don't need to cast, you don't need "as" either.


I find that inheritance is overrated. I only use it occasionally within
my own classes. It's invaluable when it's really required, but the
design requirements for a class which is meant to be inherited from are
much higher than other classes - the interaction between methods needs
to be fully documented as part of the interface, and then the
implementation has to pretty much stay the same. I prefer composition
over inheritance most of the time.
First, here is fundamental difference. I *don't want* to throw. If I am
going to throw, I know there is a *huge* overhead.


Well, there's a ~0.001ms overhead. I don't think that's huge, unless
you're planning to do it thousands of times - which basically isn't
going to happen here.


For a single instruction on a 3.0 Ghz box that's huge. At that rate, I would
only be able to execute 1000 instuctions a second.


No, you'd be able to execute nearly 1,000,000 instructions a second -
that figure was in milliseconds, not seconds. (It had a typo though - I
meant ~0.01ms, at which point you can execute it roughly 100,000 times
a second). The important thing is, however, that you won't be doing it
100,000 times a second.
But, my tests indicated it was a higher hit than that.
But your tests appear to have been run under the debugger.
Validating UI *input* should almost always involve checking (although
not so much for performance reasons - a human in front of a UI
certainly can't hit keys or move the mouse quickly enough to make it a
problem to throw an exception every time they do so). Validating
whether a control is actually what it should be? That doesn't need
checking manually. If it's wrong, the code itself is screwed up.


Well that depends. We usually build dynamic screens. And, the users can drag
and drop UI components from one panel to the other. We mimic a lot of what
VS 2003 does but for our application.


So you validate it once early on, and then you shouldn't need to do it
afterwards. Anyway, this sounds like a specialised situation which
wasn't indicated in the OP's post. I hope you'll agree that most UIs
*aren't* dynamic.
In this particular case - what about when you're passing it elsewhere,
or not using it immediately?


Depends on the elsewhere. But I don't tend to get values here for use
elsewhere. Unless elsewhere is another responsibility, but then again, if
its not responsible, that must make me, so I would need to do the
validation.


That's a whole chain of reasoning I don't need to worry about. I like
not having to think, getting the error checking for free. The more I
have to think, the more chance I have to get it wrong.
I don't know how you would know based on the code shown if a user
conversion
exists or not.


Because there's no defined conversion between Control and TextBox.
Operators are overloaded, not overridden - it's a compile-time thing,
not a run-time thing. If the actual control were some third-party
control which didn't inherit from TextBox, but had a user-defined
conversion to it, that wouldn't be performed in the casting case,
because the compiler doesn't know about it at compile-time.


Quite. True, our code is down-casting our special textbox classes to one of
the classes in its lineage.

public static implicit operator TextBox(SuperDuperTextBox control)
{
// conversion code
}


If SuperDuperTextBox is actually a TextBox already, that's not a valid
operator. However, in the case that the OP posted, the compiler isn't
going to know that the cell's value is actually a SuperDuperTextBox
anyway, so it can't use the user-defined conversion in the first place.
I believe you are artificially worried about performance, perhaps
partly based on previous bad experiences of very odd situations such as
the one you mentioned where you didn't know what resources were in an
assembly. (Any reason not to find them out using
GetManifestResourceNames? Better than asking speculatively in that
situation, I'd say.)


I wish it had been that easy. But, performance if not artificial. And, the
systems I have written do not suffer from these issues. Sure, I base the
things I do on history. Experience has been a great teacher for me. Hence my
points.


It sounds like experience *hasn't* been a great teacher though - it's
taught you to fear exceptions like they were the plague, bending code
out of shape to avoid throwing it, as in the case of the code you
showed for dealing with resources. The problem in that case wasn't that
you were throwing lots of exceptions, it was the *reason* you were
throwing lots of exceptions - namely that your resources were broken.
The fix for that isn't to ignore resources which should be there but
aren't, but to make sure that you only ask for what you need, and that
everything you need is present.

You've admitted that you've never run into a situation where decent
code has been significantly slowed down by exceptions, but you're still
coding as if they're about to slow your app down to a crawl at any
minute.
I don't think either of these methods bloats the code. One is just faster
than the other. (Not bloat; performance) And the slower casting method
does
not afford me any value add.


Whereas it gives me the following benefits:
1) Shorter code where the main success path is clearer, not hidden by
potential errors which can be handled (by throwing) by the runtime

2) Less room for accidentally forgetting the nullity check.


The code is not any shorter or longer. Cast versus "as". Not anymore clear.
In fact, hidden exception handling is who knows where. Its more comlpe.


No, the exception handling is very predictable, whereas if you use
"as" it's somewhere separate from the change of reference type. It's
wherever it's first used - and *that's* "who knows where".
Did you forget? I thought you wanted to throw? :)
Which the cast does, if anything's wrong.
This is no different than
forgetting to add the hanlder code. Or anything else for that matter. You do
step through your code in the debugger when you write it don't you?


Nope. I try to avoid using the debugger whenever possible. I write unit
tests instead. Much more reliable. I regard having to resort to the
debugger as a partial admission of failure in the first place - it
means my code isn't clear enough to be able to spot a problem just from
the place that the unit test fails, or (worse) my unit tests aren't
good enough to spot a problem which has cropped up later on.
I don't think I've been any less respectful to you than you have to me.


Not disrespect. I just found that you took exception (no pun intended) to my
comments in several post, yet steered clear of others. I just wondered if
you had something against me, or if you were after interllectual discussion.

You do seem adamant. But then again, so do I. :)


Like I said, I don't have time to read and respond to every post, but I
can point you in the directions of several times when I've had similar
"exceptions are hugely damaging to performance" discussions.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #14

This discussion thread is closed

Replies have been disabled for this discussion.