Re: What does it mean?

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



Intellectuals solve problems; geniuses prevent them. ~ Albert Einstein
"Jon Skeet [C# MVP]" <skeet@xxxxxxxxx> wrote in message
news:MPG.1d13423c649a464c98c2bc@xxxxxxxxxxxxxxxxxxxxxxx
> Frisky <Frisky_NOSPAM@xxxxxxxxxxxxx> 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 - <skeet@xxxxxxxxx>
> http://www.pobox.com/~skeet
> If replying to the group, please do not mail me too


.



Relevant Pages

  • Re: What does it mean?
    ... > runtime type matches the sought type. ... > BusinessType myBusiness = Factory.CreateObjectas BusinessType; ... > catch (Exception ex) { ... This is not a private array. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Inheriting from array of System.Diagnostics.Process[]
    ... I still don't understand - once I have received the Processarray, ... From some reason, it raised an exception. ... A simple cast, like: ... (Once I manage to cast a single object, I pass it through "foreach" and ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: What does it mean?
    ... > But, if you would like to save yourself all of the exception processing, a ... (That's what a cast does internally.) ... > control array is a particular control. ... >> where the result isn't a TextBox, ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Copying an array slice (Was: Re: Difficulties with passing multi-dimensional arrays)
    ... > the pointer to array of unknown size. ... but it still compiles without a cast. ... unknown at compile time so nothing can be checked. ...
    (comp.lang.c)
  • Re: What does it mean?
    ... >> But, if you would like to save yourself all of the exception processing, ... But "as" is at least as fast, or faster than a cast. ... >> Control. ... >>> where the result isn't a TextBox, ...
    (microsoft.public.dotnet.languages.csharp)