Is is as or is as is?

Is is as or is as is?

Rate This
  • Comments 35

Today a question about the is and as operators: is the is operator implemented as a syntactic sugar for the as operator, or is the as operator implemented as a syntactic sugar for the is operator? More briefly, is is as or is as is?

Perhaps some sample code would be more clear. This code

bool b = x is Foo;

could be considered as a syntactic sugar for

bool b = (x as Foo) != null;

in which case is is a syntactic sugar for as. Similarly,

Foo f = x as Foo;

could be considered to be a syntactic sugar for

var temp = x;
Foo f = (temp is Foo) ? (Foo)temp : (Foo)null;

in which case as is a syntactic sugar for is. Clearly we cannot have both of these be sugars because then we have an infinite regress!

The specification is clear on this point; as (in the non-dynamic case) is defined as a syntactic sugar for is.

However, in practice the CLR provides us instruction isinst, which ironically acts like as. Therefore we have an instruction which implements the semantics of as pretty well, from which we can build an implementation of is. In short, de jure is is is, and as is as is is, but de facto is is as and as is isinst.

I now invite you to leave the obvious jokes about President Clinton in the comments.

  • This is interesting.  However, why should I, as a programmer who wants to get things done, actually care?

    I reject the premise of the question; I'm not saying that you or anyone else should care about this specification/implementation detail. I don't understand what moral questions about what you should and should not care about come into it.

    To clarify: the question seems predicated on the syllogism: "Eric writes about things that are important for developers to understand; Eric wrote about the relationship between the is and as operators; therefore Eric thinks that knowing this relationship is important." Were that the case then it would be reasonable to ask why I think this is important, but it is not the case. That syllogism is based on a first premise which is false, and therefore the conclusion does not follow. I do not necessarily write about things that are important for developers to understand; I write about things that are fabulous! And the person who gets to decide what is fabulous is me. If some of those fabulous things happen to be important, that's super, but that's not my aim. The name of the blog is not "Important Stuff You Should Know About Coding".

     - Eric

  • @Brian: it means that "if (foo is Bar) { UseBar((Bar)foo); } has no worse performance than "var bar = foo as Bar; if (bar != null) { UseBar(bar); }", which is good to know, I can feel good about using the pretty code.

  • @Simon: I'll use pretty code regardless and totally and deliberately ignore any possible differences until my code has performance problems, at which point I'll use a profiler.  I think it highly unlikely that this type of syntactic sugar will be the bottleneck, and think that if the bottleneck *is* something this low level, then I probably have bigger concerns.

    So, I don't really consider efficiency to be a reason to care.  At profiling point of something that low level I'd be apt to be trying both regardless, checking the spec, or examining the IL.

  • Do you mean "bool b = (x as Foo) != null" ?

    %)

    Was a typo. Corrected. Thanks! - Eric

  • > isinst, which returns a bool

    I think you're wrong - AFAICT the CIL instruction isinst actually acts like the "as" operator (i.e. it returns the instance unmodified if the type-check passes or null otherwise).  See ECMA-335 partition III section 4.6.

    You are correct and I am WRONG WRONG WRONG. I was misremembering the codegen. I've updated the text. Thanks! - Eric

  • Paul is right.  "isinst" works like "as".  To save anyone else looking up the text:

    The isinst instruction tests whether obj (type O) is an instance of class. class is a metadata token (a typeref,

    typedef or typespecsee Partition II) indicating the desired class. If the class of the object on the top of the

    stack implements class (if class is an interface) or is a derived class of class (if class is a regular class), or if

    class is System.Nullable<T> and the object’s class is of type T, then it is cast to the type class and the result is

    pushed on the stack, exactly as though castclass had been called. Otherwise null is pushed on the stack. If obj

    is null, isinst returns null.

  • Personally, I think this entire post is about covering your as.

  • "is is is, and as is as is is"

    Sharpnglish :)

  • 8 posts and no obvious Clinton jokes?  Maybe if you made this a programming challenge there's be more traction :)

  • Doesn't the compiler also perform static analysis on the expression and elide the codegen entirely if the result is known at compile time? For example:

    bool b = 5 is int;  // or ...

    string s = "abc" as string;

    can be determined entirely statically.

    Yes, those are codegen'd as though they were constants. The compiler should produce a warning in such cases. This strategy has caused some bugs over the years where the C# and CLR rules are slightly different: see this post for details. Introducing variant conversions in C# 4 also caused some bugs in this optimization. - Eric

  • @Brian

    Some people actually write code where computations are the bottleneck. See scientific and financial community for example. Every instruction counts and using the right language features in the right place can avoid  the need to go for low-level languages like C, or having to do some crazy interop.

    @Eric

    Do you recommend any good book or resource that goes deeply into the CLR and IL?

  • Does anyone anywhere program in actual MSIL? If I were to want to do that (for some unknown and maybe unknowable reason), suggestions on how to get started?

  • Here's a vote for continued fabulousness without fabulation.  Leave the pizzazz as is.

  • While I 100% agree with rite clean code, and look at performance when there is a measurement (against a specification) that warrants it...it still drives me nuts to see:

      if (myObj is MyClass)

        {

          MyClass myClass = myObj as MyClass;

          myClass.Method();

        }

    Unfortunately I run into it in code far too often....

  • @Diego: Fair enough.  Perhaps my response is too personalized to be a contribution to this discussion.

    @Eric: I was more interested in an answer to the question "Is knowing the answer to this question important to programmers who want to get things done important? If so, when?"  Simon/Diego discussed one such answer.

Page 1 of 3 (35 items) 123