tags:

views:

706

answers:

11

In Jesse Liberty's Programming C# (p.142) he provides an example where he casts an object to an interface.

 interface IStorable
 {
    ...
 }

 public class Document : IStorable
 {
    ...
 }

 ...
 IStorable isDoc = (IStorable) doc;  
 ...

What is the point of this, particularly if the object's class implements the inteface anyway?

EDIT1: To clarify, I'm interested in the reason for the cast (if any), not the reason for implementing interfaces. Also, the book is his 2001 First Edition (based on C#1 so the example may not be germane for later versions of C#).

EDIT2: I added some context to the code

+7  A: 

If the object implements the interface explicitly (public void IStorable.StoreThis(...)) that casting is the easiest way to actually reach the interface members.

James Curran
is there an other way to reach the explicit interface members?
Svish
+8  A: 

Because you want to restrict yourself to only methods provided by the interface. If you use the class, you run the risk of calling a method (inadvertently) that's not part of the interface.

Tundey
Can you not do IStorable isDoc = doc; if doc is an instance of an implementing class of IStorable? The cast seems superfluous, unless I'm mixing up Java and C#. (I've not done C# in a while, sadly).
Devin Jeanpierre
@Devin: Yes, the cast is superfluous as long as doc is declared to be a type which implements the interface.
Jon Skeet
Doesn't the reference itself restrict you from calling any methods outside the interface?
Bill the Lizard
@Bill: No it doesn't.
Tundey
+6  A: 

It's pretty hard to tell without more of the context. If the variable doc is declared to be a type which implements the interface, then the cast is redundant.

Which version of the book are you reading? If it's "Programming C# 3.0" I'll have a look tonight when I'm at home.

EDIT: As we've seen in the answers so far, there are three potential questions here:

  • Why cast in the statement shown in the question? (Answer: you don't have to if doc if of an appropriate compile-time type)
  • Why is it ever appropriate to explicitly cast to an implemented interface or base class? (Answer: explicit interface implementation as shown in another answer, and also for the sake of picking a less specific overload when passing the cast value as an argument.)
  • Why use the interface at all? (Answer: working with the interface type means you're less susceptible to changes in the concrete type later on.)
Jon Skeet
The "(IStorable)" cast also aids readability by explicitly stating that "doc" is NOT an "IStorable" object, but rather something that can be cast as an "IStorable". Although superfluous, it adds that piece of information for anyone who may be reading the code later.
I don't see how that's a useful bit of information - in fact, it implies (to me) that the doc variable is of a type which *requires* an execution-time check (which sounds like it's not the case here). That's misleading.
Jon Skeet
+3  A: 

The doc object might be of a type that implements members of IStorable explicitly, not adding them to the classes primary interface (i.e., they can only be called via the interface).

Actually "casting" (using the (T) syntax) does not make any sense since C# handles upcasts (cast to parent type) automatically (unlike F# for instance).

SealedSun
A: 

The point is, the object (where did you get it?) may not implement the interface, in which case an exception is thrown which can be caught and dealt with. Of course you can use the "is" operator to check, and the "as" operator to cast instead of the C-style cast.

royatl
Could someone please explain why you voted this down? Thanks.
royatl
+3  A: 

I am not sure under what context the example was given in the book. But, you generally can type cast an object to interface to achieve multiple inheritance. I have given the example below.

public interface IFoo
{
     void Display();
}
public interface IBar
{
     void Display();
}

public class MyClass : IFoo, IBar
{
    void IBar.Display()
    {
        Console.WriteLine("IBar implementation");
    }
    void IFoo.Display()
    {
        Console.WriteLine("IFoo implementation");
    }
}

public static void Main()
{
    MyClass c = new MyClass();
    IBar b = c as IBar;
    IFoo f = c as IFoo;
    b.Display();
    f.Display();
    Console.ReadLine();
}

This would display

IBar implementation
IFoo implementation

Ramesh
+5  A: 

There is only one reason when you actually need a cast: When doc is of a base type of an actual object that implements IStorable. Let me explain:

public class DocBase
{
  public virtual void DoSomething()
  {

  }
}

public class Document : DocBase, IStorable
{
  public override void DoSomething()
  {
    // Some implementation
    base.DoSomething();
  }

  #region IStorable Members

  public void Store()
  {
    // Implement this one aswell..
    throw new NotImplementedException();
  }

  #endregion
}

public class Program
{
  static void Main()
  {
    DocBase doc = new Document();
    // Now you will need a cast to reach IStorable members
    IStorable storable = (IStorable)doc;
  }
}

public interface IStorable
{
  void Store();
}
Jeroen Landheer
Thanks, but this confuses me a little. Why would you use the base type DocBase when creating the Document object?
eft
One reason could be that you're using a factory to construct objects and it returns objects as their base types.
Chetan Sastry
There can be any numbers of reasons. What I see mostly is by implementing base classes that are shipped by 3rd parties and do not have an interface specified. In that case the "DocBase" class comes out of a different library and is implemented with an interface in your own code.
Jeroen Landheer
+1  A: 

As has been noted, the casting is superfluous and not necessary. However, it is a more explicit form of coding which would be useful to beginners in aiding their understanding.

In an introductory textbook, it is best to explicitly act, rather than let the compliler do things implicitly, which would be more confusing for beginners.

The "doc" is not of type "IStorable" so it would be confusing for beginners to see that it is being assigned to a isDoc. By explicitly casting, the author (of the book and of the code) is saying that a document can be casted to an IStorable object, but it is NOT THE SAME as an IStorable object.

+1  A: 

There are a lot of good answers here, but I don't really think they answer WHY you actually WANT to use the most restrictive interface possible.

The reasons do not involve your initial coding, they involve the next time you visit or refactor the code--or when someone else does it.

Let's say you want a button and are placing it on your screen. You are getting the button either passed in or from another function, like this:

Button x=otherObject.getVisibleThingy();
frame.add(x);

You happen to know that VisibleThingy is a button, it returns a button, so everything is cool here (no cast required).

Now, lets say that you refactor VisibleThingy to return a toggle button instead. You now have to refactor your method because you knew too much about the implementation.

Since you only NEED the methods in Component (a parent of both button and Toggle, which could have been an interface--same thing pretty much for our purposes), if you had written that first line like this:

Component x=(Component)otherObject.getVisibleThingy();

You wouldn't have had to refactor anything--it would have just worked.

This is a very simple case, but it can be much more complex.

So I guess the summary would be that an interface is a specific way to "View" your object--like looking at it through a filter...you can only see some parts. If you can restrict your view enough, the object can "Morph" behind your particular view and not effect anything in your current world--a very powerful trick of abstraction.

Bill K
A: 

The best reason why you would cast to interfaces would be if you are writing code against objects and you don't know what concrete type they are and you don't want to.

If you know that you might come across an object that implements a specific interface you could then get the values out of the object without having to know the concrete class that this object is. Also, if you know that an object implements a given interface, that interface might define methods that you can execute to take certain actions on the object.

Here's a simple example:

public interface IText
{
   string Text { get; }
}

public interface ISuperDooper
{
   string WhyAmISuperDooper { get; }
}

public class Control
{
   public int ID { get; set; }
}

public class TextControl : Control, IText
{
   public string Text { get; set; }
}

public class AnotherTextControl : Control, IText
{
   public string Text { get; set; }
}

public class SuperDooperControl : Control, ISuperDooper
{
   public string WhyAmISuperDooper { get; set; }
}

public class TestProgram
{
   static void Main(string[] args)
   {
      List<Control> controls = new List<Control>
               {
                   new TextControl
                       {
                           ID = 1, 
                           Text = "I'm a text control"
                       },
                   new AnotherTextControl
                       {
                           ID = 2, 
                           Text = "I'm another text control"
                       },
                   new SuperDooperControl
                       {
                           ID = 3, 
                           WhyAmISuperDooper = "Just Because"
                       }
               };

       DoSomething(controls);
   }

   static void DoSomething(List<Control> controls)
   {
      foreach(Control control in controls)
      {
         // write out the ID of the control
         Console.WriteLine("ID: {0}", control.ID);

         // if this control is a Text control, get the text value from it.
         if (control is IText)
            Console.WriteLine("Text: {0}", ((IText)control).Text);

         // if this control is a SuperDooperControl control, get why
         if (control is ISuperDooper)
            Console.WriteLine("Text: {0}", 
                ((ISuperDooper)control).WhyAmISuperDooper);
      }
   }
}

running this little program would give you the following output:

ID: 1

Text: I'm a text control

ID: 2

Text: I'm another text control

ID: 3

Text: Just Because

Notice that I didn't have to write any code in the DoSomething method that required me to know anything about all the objects I was working on being concrete object types. The only thing that I know is that I'm working on objects that are at least an instance of the Control class. I can then use the interface to find out what else they might have.

There's a million different reasons that you would take this approach with interfaces on your objects but it gives you a loose way to access your objects without having to know exactly what it is.

Think of all the credit cards in the world, every company makes their own, the interface is the same though, so every card reader can have a card swiped through it that follows the standard. Similar to the usage of interfaces.

Code Monkey
A: 

To allow for the most decoupling between pieces of code...

See the following article for more: Interfaces

Tom Deleu