Edward Tanguay
Edward Tanguay

Reputation: 193302

Is there more to the C# "as" keyword than simple casting?

I'm working through Josh Smith's CommandSink code obviously do not understand something about the "as" keyword in C#.

I don't understand why he wrote the line:

IsValid = _fe != null || _fce != null;

since he only needed to write:

IsValid = depObj != null;

Since it would never be the case the _fe would be null and _fce not null, or visa versa, right? Or am I missing something about how "as" casts variables?

class CommonElement
{
    readonly FrameworkElement _fe;
    readonly FrameworkContentElement _fce;

    public readonly bool IsValid;

    public CommonElement(DependencyObject depObj)
    {
        _fe = depObj as FrameworkElement;
        _fce = depObj as FrameworkContentElement;

        IsValid = _fe != null || _fce != null;
    }
    ...

ANSWER:

The answer is what Marc said in his comment "that is the whole point of "as" - it won't throw an exception - it just reports null."

and here is the proof:

using System;

namespace TestAs234
{
    class Program
    {
        static void Main(string[] args)
        {
            Customer customer = new Customer();
            Employee employee = new Employee();

            Person.Test(customer);
            Person.Test(employee);
            Console.ReadLine();
        }

    }

    class Person
    {
        public static void Test(object obj)
        {
            Person person = obj as Customer;

            if (person == null)
            {
                Console.WriteLine("person is null");
            }
            else
            {
                Console.WriteLine("person is of type {0}", obj.GetType());
            }
        }
    }

    class Customer : Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

    class Employee : Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

}

Upvotes: 11

Views: 6881

Answers (6)

Michael Klement
Michael Klement

Reputation: 3415

First, the as keyword includes a is check.

if( o is A)
   a = (A) o;

is the same as

a = o as A;

Second, as does not convert the Type like a cast does, even if a conversion operator from Type A to B is defined.

Upvotes: 2

peterchen
peterchen

Reputation: 41096

as does "cast, if it is", and equivalent to:

(X is TYPE) ? (TYPE) X : null

it is however, more efficient than is + cast.

depObj may implement either interface, none, or both.

Upvotes: 5

Marc Gravell
Marc Gravell

Reputation: 1062600

What if depObj is neither a FrameworkElement or a FrameworkContentElement? I don't know the full scenario (i.e. what the types are likely to be), but this seems a reasonable defensive strategy.

Upvotes: 2

Eoin Campbell
Eoin Campbell

Reputation: 44268

What if the DependencyObject depObj was actually a FrameworkOtherTypeOfElement

Then depObj would not be null

but the attempted as Casts would both evaluate to null and _fe & _fce would both be null

as is equivalent to doing

if(I Can Cast This Object)
   //Then cast it
else
   //Return null

Upvotes: 1

Darin Dimitrov
Darin Dimitrov

Reputation: 1038720

IsValid = _fe != null || _fce != null;

and

IsValid = depObj != null;

are not the same tests because if depObj is not of type FrameworkElement nor FrameworkContentElement but is not null the second test will return true, while the first will return false.

Upvotes: 4

Simon Broadhead
Simon Broadhead

Reputation: 3483

as will return an object of the type you requested, if the operand is compatible. If it isn't, it will return null. If you use as and it is possible that the cast will fail, you need to check to make sure the reference is valid.

For example, if depObj was of type String, it would not be null, but it would also not be able to be converted to either of the requested types and both of those variables would become null.

Upvotes: 26

Related Questions