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.

  • What's the purpose of casting null to Foo in the last code example?

  • @David: in the world of impossible hypotheticals, how about this neat little syntactic transformation

    try (myObj as MyClass)

    {

       myObj.Method()

       ....

    }

    the actual keyword (try) is not so important; more important is that in the try scope, myObj would be typed as MyClass and would only enter if myObj is MyClass and it wouldn't be possible to use the syntax

    var x as T

    because that would still let you use something that is null. Correct by construction would be nice, but that's for a parallel universe...

    If I remember correctly, in Cw there is a nice null propagation semantics so maybe you can do something like myObj.Method() without null fear (with "null" fear?).. maybe not...

  • In the past I have also wished for something like Bent's suggestion, but I would make it more general/universal by inferencing the type of local variables as long as this is safely possible:

    var x = Whatever();

    if (x is IDisposable) {

     x.Dispose(); // the compiler knows that x is a IDisposable here

    }

    x.Dispose() // compiler error here, x may not be a IDisposable

    This would make local variables behave more like variable of a generic type argument with constraints, where the compiler also "knows" hat the constrained type will be of a specific class and implement some specific interfaces, so that those methods can be called without requiring a cast.

  • by the way .... so romantic title for the article

  • Various posters have already pointed this out and shown a number of variants: C# code is riddled with clumsy constructs like

    Foo f = x as Foo;
    if ( x != null )
       x.DoSomething();

    and

    if ( x is Foo )
       ((Foo) x).DoSomething();

    C# simply doesn't have any good syntax for this. C++ offers the following elegant and well-defined construct (translated to C#):

    if ( var f = x as Foo )
       f.DoSomething();

    The C++ Standard interprets it as follows: "The value of a condition that is an initialized declaration [...] is the value of the declared variable implicitly converted to type bool."

    C# does not have such implicit conversions, but if we restrict the type (Foo) to being a reference type, then the condition could be defined strictly as whether the variable (f) is non-null. This would also be useful in constructs like

    if ( var item = dictionary[key] )
      item.DoSomething();

    Support for defining references in if-statements would eliminate a lot of tedious and distracting null comparisons, and it has the advantage of automatically restricting the scope of the variable to where it is useful.

Page 3 of 3 (35 items) 123