C Sharp

Querying for Implementation by Using is

In the InterfaceApp example, you saw the following code, which was used to cast an object (MyControl) to one of its implemented interfaces (IValidate) and then call one of those interface members (Validate): -

MyControl myControl = new MyControl();
image
IValidate val = (IValidate)myControl;
bool success = val.Validate();

What would happen if a client attempted to use a class as if the class had implemented a method that it hadn't? The following example will compile because ISerializable is a valid interface. Nonetheless, at run time a System. InvalidCastException will be thrown because MyGrid doesn't implement the ISerializable interface. The application would then abort unless this exception was being explicitly caught.

using System;
public class FancyControl
{
    protected string Data;
    public string data
    {
        get
        {
            return this.Data;
        }
        set
        {
            this.Data = value;
        }
    }
}
interface ISerializable
{
    bool Save();
}
interface IValidate
{
    bool Validate();
}
class MyControl : FancyControl, IValidate
{
    public MyControl()
    {
        data = "my grid data";
    }
    public bool Validate()
    {
        Console.WriteLine("Validating...{0}", data);
        return true;
    }
}
class IsOperator1App
{
    public static void Main()
    {
        MyControl myControl = new MyControl();
        ISerializable ser = (ISerializable)myControl;
        // NOTE: This will throw a System.InvalidateCastException
        // because the class does not implement the ISerializable
        // interface.
        bool success = ser.Save();
        Console.WriteLine("The saving of '{0}' was {1}successful",
 myControl.data,
 (true == success ? "" : "not "));
    }
}

Of course, catching the exception doesn't change the fact that the code you want to execute will not execute in this case. What you need is a way to query the object before attempting to cast it. One way of doing this is by using the is operator. The is operator enables you to check at run time whether one type is compatible with another type. It takes the following form, where expression is a reference type: -

expression is type -

The is operator results in a Boolean value and can, therefore, be used in conditional statements. In the following example, I've modified the code to test for compatibility between the MyControl class and the ISerializable interface before attempting to use an ISerializable method: -

using System;
public class FancyControl
{
    protected string Data;
    public string data
    {
        get
        {
            return this.Data;
        }
        set
        {
            this.Data = value;
        }
    }
}
interface ISerializable
{
    bool Save();
}
interface IValidate
{
    bool Validate();
}
class MyControl : FancyControl, IValidate
{
    public MyControl()
    {
        data = "my grid data";
    }
    public bool Validate()
    {
        Console.WriteLine("Validating...{0}", data);
        return true;
    }
}
class IsOperator2App
{
    public static void Main()
    {
        MyControl myControl = new MyControl();
        if (myControl is ISerializable)
        {
            ISerializable ser = (ISerializable)myControl;
            bool success = ser.Save();
            Console.WriteLine("The saving of '{0}' was {1}successful",
myControl.data,
(true == success ? "" : "not "));
        }
        else
        {
         Console.WriteLine("The ISerializable interface is not implemented.");
        }
    }
}

Now that you've seen how the is operator enables you to verify the compatibility of two types to ensure proper usage, let's look at one of its close relatives-the as operator-and compare the two.