14

I have -never- used as or is in C# or any language that supports the keyword.

What have you used it for?

I dont mean how do i use it i mean how have you actually need it?

I also got away with doing no typecasting in a fairly large c++ project (i was proud).

So considering i almost never typecast why do i need the keyword as or is?

David Basarab
  • 72,212
  • 42
  • 129
  • 156
  • 2
    The main advantage of "as" is that it won't throw an exception when cast is invalid. Direct type cast would. – Robert Koritnik Oct 15 '09 at 13:18
  • 3
    Depends on the what the meaning of as is. ;) – kenny Oct 15 '09 at 14:53
  • See also "When to use run-time type information?" at http://stackoverflow.com/questions/1520466 – ChrisW Oct 15 '09 at 15:14
  • 2
    I don’t want to be over-critical but I cannot imagine a large .NET code to be cleanly designed and not requiring any casts at all. Of course casts are to be avoided but there are simply situations in .NET where they *cannot* be avoided, only at the cost of a very bad design. Consider the example of overriding `Equals`, given in the answers below. You never overrode `Equals` in your code? Wow. – Konrad Rudolph Oct 16 '09 at 10:05
  • @Konrad: Note that i said C++. We had many overloaded operator and we had classes that returned operator AnotherClass(); It was roughly 10kloc although that may not be large to some people. –  Oct 16 '09 at 11:46
  • 1
    What isn't really clear from the answers: `as` and `is` only work on `reference types` not on `value types`. If you need to cast to `int`, `double`, `IntPtr`, `DateTime` etc, you need to use a classic cast. Using `is` or `as` for `Nullable` types like `int?` etc _is_ fine of course. – Abel Oct 17 '09 at 09:39

14 Answers14

34

I had to write code to enumerate over all the controls placed on a ASP.NET webform and perform certain operations on specific controls, e.g. add a background color to all Textboxes, and so on.

The main benefit of as and is for me is that I can safely check whether a variable is of a given type using is without exceptions happening. Once I'm sure it's of a given type, I can safely and easily convert it to the type needed using as.

What I basically did (simplified!) is a

foreach(Control c in form.Controls)
{
   if(c is Textbox)
      HandleTextbox(c as Textbox);

   if(c is Listbox)
      HandleListbox(c as Listbox);
}

and so on. Without as and is this would be a lot messier, IMHO.

Basically, you'll probably need or can make good use of as and is if you're dealing with polymorphism a lot - if you have lists of things that can be any number of types, like controls on a page in my example. If you don't have or don't use polymorphism a lot, you're unlikely to encounter the need for those operators.

Marc

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • 4
    You might as well cast here. You have already used the is to test your object for the correct type. http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx – Matthew Whited Oct 15 '09 at 13:22
  • 2
    @Matthew: yes you could - do you think that's easier/more readable? I don't think so.... – marc_s Oct 15 '09 at 13:23
  • If you know C# it's not any less readable. But it does to less work. – Matthew Whited Oct 15 '09 at 13:31
  • Perfect! To enum through a form control to find a specific control and to do operations with it! kind of like iterating through a directory to either find files to compress or folders to recurse into :). I cant think of any reason WHY you need to iterate to find and handle Textboxes, Listboxes etc but i am sure a reason exist. It make sense that all controls are all in one container or enum unlike how Directory.GetFile and GetDirectory works (2 seperate enums) –  Oct 15 '09 at 13:34
  • 4
    I take back the more work. I just ran a test and at least for strings the "as" operator (IsInst opcode) seems to be faster than cast (CastClass opcode)... But "As" and null check is the fastest (assuming you want the instance and not just the type check. It should be pointed out that "as" only works with classes. – Matthew Whited Oct 15 '09 at 13:55
  • Just a thought, not necessarily prettier: instead of `if..if..` etc, consider writing `HandleControl(Textbox)`, `HandleControl(Listbox)` overrloads. Now the foreach-body becomes a few lines only: `HandleControl(c as Textbox)`, `HandleControl(c as Listbox)` etc. No if-statements anymore. – Abel Oct 15 '09 at 14:34
  • I'm with @Matthew Whited here, you should be handling the possibility of null paramenters in your methods and simply do MyMethod(c as Type). – snicker Oct 15 '09 at 15:14
  • 10
    The best form (and the one you should be using instead of the one above) is `Textbox tb = c as Textbox; if (tb != null) HandleTextbox(tb);` – Sam Harwell Oct 15 '09 at 15:16
  • @280Z28: yes, that's what I ended up doing in the end, as an refactoring. Works even better. – marc_s Oct 15 '09 at 15:32
  • @snicker: yes, of course - this is code written quite a few years ago and I've improved my .NET skills since then :-) But this wasn't about the optimal way of enumerating controls on a form - but about how and when to use "as" and "is" – marc_s Oct 15 '09 at 15:33
  • @acidzombie: well, at that time, I needed to enumerate the controls - and unfortunately, there's no "GetAllTextboxes()" and "GetAllListboxes()" methods on the ASP.NET form..... so I couldn't rely on a more focused enumeration. – marc_s Oct 15 '09 at 15:34
  • 2
    whenever i see something of this form, something in me screams "use polymorphism!!!!" – RCIX May 21 '10 at 02:08
15

I use 'as' as a handy shortcut in event handlers to get the sending object back when I can't know at design time the sender.

protected void SomeButtonInAGridView_Click(object sender, EventArgs e)
{
    Button clickedButton = sender as Button;
}
DavidGouge
  • 4,583
  • 6
  • 34
  • 46
  • 2
    +1. Very good for reusing event handlers, a very good practice. – Matthew Scharley Oct 15 '09 at 13:11
  • funny how I needed so many more words to explain the same. Nice example! – Abel Oct 15 '09 at 13:20
  • I dont understand. It seems like you are always excepting a button and also what case would you set this as a callback where the sender is NOT a button? –  Oct 15 '09 at 13:26
  • 2
    Yes, I know it will always be a button, but to get access to the clicked button properties I feel that syntax is much cleaner and easier to read than Button clickedButton = (Button)sender; – DavidGouge Oct 15 '09 at 13:29
  • Not just "feel like" better - you avoid runtime errors and allow handlers to be reusable for multiple types of controls by using as-null. – Rex M Oct 15 '09 at 22:52
10

Here's one that comes up alot:

class Foo {
     public override bool Equals(object obj)
     {
         // The more specific function needs to do null checking anyway.
         return Equals(obj as Foo);
     }

     public bool Equals(Foo obj)
     {
         // do some comparison here.
     }
}
Matthew Scharley
  • 127,823
  • 52
  • 194
  • 222
  • This is a spot were "is" would be better – Matthew Whited Oct 15 '09 at 13:19
  • not really if you need to continue on the Foo object, using `is` always involves two cast conversion actions (comparison with `is` and casting), while casting once and testing for null seems slightly more efficient. Casting, `as` and `is` are highly optimized though, so in practice it's merely a matter of taste. – Abel Oct 15 '09 at 13:23
  • 2
    Not really. If you use `is`, then you need to then cast to `Foo` to be able to do the comparison (unless all Foo's are equal!). – Matthew Scharley Oct 15 '09 at 13:23
  • 2
    That said, Microsoft suggests using an overload: `Equals(Foo)` and `override Equals(object)`. This takes away the burden of casting and gives cleaner code altogether – Abel Oct 15 '09 at 13:27
  • Good point. I was only look at is as if we was using it only for the conditional. – Matthew Whited Oct 15 '09 at 13:27
  • @Abel: Even if you implement an `Equals(Foo)` method, you still need to override the default version and use is/as to do typechecks before passing it up to `Equals(Foo)`. – Matthew Scharley Oct 15 '09 at 13:29
8

Intriguing question. Actually, I use them all the time. is is handy to find out whether an object is of a certain type, I use that occasionally in generics or in loops through objects that are of different types. It is also invaluable with Reflection.

The other, as finds many more uses. It is often much safer to use then a normal cast: when it fails, it returns null, instead of an exception. I also find it clearer syntax and easier to use it, check the return value for null, then to add an exception block.

Basically, what I mean to say is, I prefer this:

protected void GeneralEventHandler(object sender, EventArgs e)
{
    Button btn = sender as Button;
    if(btn != null)   // click came from a button!
        // do something
    else
        // other cases
}

and this:

protected void GeneralEventHandler(object sender, EventArgs e)
{
    if(sender is Button)   // click came from a button!
        // do something
    else
        // other cases
}

as opposed to this:

protected void GeneralEventHandler(object sender, EventArgs e)
{
    try 
    {
        Button btn = (Button) sender;
        // if we get this far, it's a button
    }
    catch(InvalidCastException ice)
    {
        // click did not come from a button! Handle other cases
    }
}

of course, this is just an example, but when I can avoid try / catch, I will. This also lets more room for real exceptions to get through.

Abel
  • 56,041
  • 24
  • 146
  • 247
7

I use it for cleanly getting data from a DataReader that might be DBNull.

int? personHeight = dr["Height"] as int?;

or

int personHeight = dr["Height"] as int? ?? 0;
Chris
  • 2,959
  • 1
  • 30
  • 46
  • +1 esp. the second case finds lots of uses with nullable types, great to include it here! – Abel Oct 15 '09 at 15:12
  • VERY good use. I'd mark this correct too if i could have more then one! :/ –  Oct 15 '09 at 15:13
3

Here is a post from Eric Lippert describing how "as" is used in C#:

http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx

I use as all the time. When i have to pull back a serialized object from session cache, I use as to determine if the serialized object is there and of the right type. I can avoid the program throwing an error, using the as operator and checking for null. If it's null, I know something is missing, and I can recreate the object and push it back into cache for the next time I need it.

You could accomplish the same result using the cast operator, but that adds the overhead of an exception, especially when you know that the serialized object isn't going to be there part of the time.

kemiller2002
  • 113,795
  • 27
  • 197
  • 251
2

C# offer way to cast using the is and as operator. The is operator checks whether an object is compatible with a given type, and the result of the evaluation is a Boolean: true or false. The is operator will never throw an exception. The following code demonstrates:

System.Object o = new System.Object();
System.Boolean b1 = (o is System.Object); // b1 is true.
System.Boolean b2 = (o is Employee); // b2 is false.

If the object reference is null, the is operator always returns false because there is no object available to check its type.

The is operator is typically used as follows:

if (o is Employee) {
Employee e = (Employee) o;
// Use e within the ‘if’ statement.
}

In this code, the CLR is actually checking the object’s type twice: the is operator first checks to see if o is compatible with the Employee type. If it is, then inside the if statement, the CLR again verifies that o refers to an Employee when performing the cast.

C# offers a way to simplify this code and improve its performance by providing an as operator:

Employee e = o as Employee;
if (e != null) {
// Use e within the ‘if’ statement.
}

In this code, the CLR checks if o is compatible with the Employee type, and if it is, as returns a non-null pointer to the same object. If o is not compatible with the Employee type,then the as operator returns null.

anishMarokey
  • 11,279
  • 2
  • 34
  • 47
2

If you ever develop on a project that offers a plugin interface then as and is will quickly become your VERY best friends.

Foxfire
  • 5,675
  • 21
  • 29
2

Here's another use-case to go into the Cabinet of Dr. Caligari ;-)

You can chain the as operator, as in:

x = obj as Label as Control;

Why would you do such a thing? If you want null if its not a Label, but you want to treat them all as Control. Just casting Textbox and Label directly to Control would yield success for both, now it'll be null for unwanted types of Control. This is a shortcut method you won't need often but is occasionally handy.

An alternative use for the same is when you need ToString() on an object, but only when it is of the correct type, otherwise you want a default string. This is a scenario that I do encounter very often, esp. with POCOs. Because ToString() is virtual, this works:

// assume SomeClass has overridden ToString()
// return "none" if item is not of type SomeClass or if it is null to begin with
string itemText = (item as SomeClass as Object ?? "none").ToString();
Abel
  • 56,041
  • 24
  • 146
  • 247
1

C-style casts (like (Foo)bar) will throw InvalidCastException if cast fails. as, on the other hand, will yield null (see this). is operator is just used to test whether a run-time type of given instance is compatible with the type provided (see this).

is is used extensively in.NET System.ComponentModel namespace. More specifically, TypeConverter API relies heavily on is operator to determine how to convert from one type to another.

Anton Gogolev
  • 113,561
  • 39
  • 200
  • 288
1

I used both keywords extensively in a WinForms app where there's a GUI to edit an invoice, each row in the ListView could contain different types of items (i.e., it could be a line item or a description, or ...). All the items I put in the ListView were derived from ListViewItem, so then later on when I went to implement things like editing the selected item, I had to check which item type was selected (using is) to show the appropriate editing GUI.

Jon Seigel
  • 12,251
  • 8
  • 58
  • 92
1

Custom TypeConverters comes first to mind.

public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value is string)
            {
                return GetEnumValue(myVal, (string)value);
            }
            if (value is Enum)
            {
                return GetEnumDescription((Enum)value);
            }
            return base.ConvertFrom(context, culture, value);
        }

Second comes from a case where I have a shadow of an object (for tracking changes) which is inherited from a base class

class BaseClass
{
    BaseClass _shadow;
}

protected override void UpdateShadow()
{
    ThisClass shadow = _shadow as ThisClass;
      //...
}
0

If you're really never having to do casting then I you likely wouldn't have much use for these operators. In my experience, however, .NET programming calls for a lot of casting particularly when dealing with delegates where arguments are provided typed as 'object'. I think that the introduction of generics has helped cut down on the need for casting, but it's certainly something that I use pretty often. I might be "doing it wrong" but that's just been my experience.

So if you're going to do casting anyway I really like the 'is' operator for improved readability of the code. I'd much rather look at

if(foo is SomeType) {...}

then

if(foo.GetType() == typeof(SomeType)) {...}
Jesse Taber
  • 2,376
  • 3
  • 23
  • 33
0

marc_s's answer is a little flawed, I see this code all the time so I want to emphasize the importance of the difference between these operators. is is a boolean test to determine if an object is assignable to a certain type. as checks to see if an object is assignable to a certain type and if it is, it returns that object as that type, if not, it returns null. marc_s's answer is really doing this

foreach(Control c in form.Controls)
{
   if(c is Textbox)
      HandleTextbox(c is Textbox ? (Textbox)c : null);

   if(c is Listbox)
      HandleListbox(c is Listbox ? (Listbox)c : null);
}

It is redundant to use is with as. When ever you use as just replace it with the expression above, it is equivalent. Use is with direct casts () or as only by itself. A better way to write that example would be.

foreach(Control c in form.Controls)
{
   if(c is Textbox)
      HandleTextbox((Textbox)c); 
      //c is always guaranteed to be a Textbox here because of is 

   if(c is Listbox)
      HandleListbox((Listbox)c); 
      //c is always guaranteed to be a Listbox here because of is 
}

Or if you really like as

foreach(Control c in form.Controls)
{
   var textBox = c as Textbox;
   if(textBox != null) 
   {
       HandleTextbox(textBox);
       continue;
   }

   var listBox = c as ListBox
   if(listBox != null)
      HandleListbox(listBox);
}

A real world example that I run into all the time is getting objects from a storage area that only return type object. Caching is a great example.

Person p;
if (Cache[key] is Person)
    p = (Person)Cache[key];
else 
    p = new Person();

I use as much less in real code because it really only works for reference types. Consider the following code

int x = o as int;

if (x != null)
   ???

as fails because an int can't be null. is works fine though

int x;
if (o is int)
    x = (int)o; 

I am sure there is also some speed difference between these operators, but for a real application the difference is negligible.

Community
  • 1
  • 1
Bob
  • 97,670
  • 29
  • 122
  • 130