Performance of operators is/as vs cast

P

Pavel Minaev

There was an earlier discussion regarding which one is faster - a
throwing cast - "(Foo)obj", or a non-throwing one - "obj as Foo", when
both are available for a given type and value. The consensus was that,
since a check has to be made by the compiler in either case, the speed
should be equivalent in case object is indeed of a requested type.
Sounds perfectly reasonable, but I've spotted the following in
the .NET source code (from MS symbol servers) today, in file
BindingList.cs, method Child_PropertyChanged:

// The change event is broken should someone pass
an item to us that is not
// of type T. Still, if they do so, detect it and
ignore. It is an incorrect
// and rare enough occurrence that we do not want
to slow the mainline path
// with "is" checks.
T item;
try {
item = (T)sender;
}
catch(InvalidCastException) {
ResetBindings();
return;
}

Now this gets interesting, since the comment clearly implies that a
throwing cast is, after all, faster than a check for the non-throw
case (and since "is" and "as" are both compiled to "isinst" IL, we
know that it is really about "castclass" vs "isinst"). I wonder how
true this really is, and if so, why is it the case. I'm going to play
with debugger to see what the JIT produces in either case later, but
perhaps someone already knows the reason?
 
M

Marc Gravell

implies that a throwing cast is, after all, faster than a check for the non-throw
No - the point here is that even if they do an "is" test, they are
*still* going to have to do the cast. BindingList<T> doesn't impose
that T : class, so "as" isn't an option, so they would have to write:

if(sender is T) {
T item = (T) sender;
}

So they've only introduced *extra* code by using "is"; the cast will
still do the check anyway. And as the comment explains, the exception
is expected to be the rare case, so it makes reasonable sense to
simply catch it if a problem happens. In reality: we are talking about
data-binding here - lots of events/delegate invokes/indirection via
System.ComponentModel. Minute things like the difference between is/as/
cast are going to be such a tiny portion of the overall CPU cost that
even if it was done the most expensive way (of the three mentioned) it
would never manifest as a bottleneck; and I'd rather MS concentrate on
the bigger picture ;-p

Marc
 
M

Marc Gravell

To be fair, I think they'd have written:

No; they *can't* have; I'll repeat: BindingList<T> does not impose
that T : class, therefore the following is invalid:

T item = sender as T;
Error 1 The type parameter 'T' cannot be used with the 'as' operator
because it does not have a class type constraint nor a 'class'
constraint

Add that in with the rest of the comments, and I think that explains
everything.

Marc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top