Interface Question

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • walt.stoneburner@gmail.com

    #1

    Interface Question

    Why does aliasing an interface fail at runtime?

    SAMPLE WORKING CODE
    ...
    IHTMLDocument2 doc = (IHTMLDocument2 ) browser.Documen t;
    ...

    BROKEN CODE
    public interface IFooBar : IHTMLDocument2 { }
    ...
    IFooBar doc = (IFooBar) browser.Documen t;
    ...

    The broken code example compiles with no errors or warnings, but causes
    an System.InvalidC astException exception at runtime, with a more
    detailed message of "Specified cast is not valid."

    What I don't get is that if my IFooBar interface inheirts from an
    interface that works and contains no other additional method
    signatures, then in theory the interfaces should be identical. Yet,
    clearly it's failing performing the cast.

    What's _really_ going on behind the scenes that explains why C# is
    doing this?

    Thanks,
    -Walt Stoneburner

  • Jon Skeet [C# MVP]

    #2
    Re: Interface Question

    <walt.stoneburn er@gmail.com> wrote:[color=blue]
    > Why does aliasing an interface fail at runtime?
    >
    > SAMPLE WORKING CODE
    > ...
    > IHTMLDocument2 doc = (IHTMLDocument2 ) browser.Documen t;
    > ...
    >
    > BROKEN CODE
    > public interface IFooBar : IHTMLDocument2 { }
    > ...
    > IFooBar doc = (IFooBar) browser.Documen t;
    > ...
    >
    > The broken code example compiles with no errors or warnings, but causes
    > an System.InvalidC astException exception at runtime, with a more
    > detailed message of "Specified cast is not valid."[/color]

    Yes, it would.
    [color=blue]
    > What I don't get is that if my IFooBar interface inheirts from an
    > interface that works and contains no other additional method
    > signatures, then in theory the interfaces should be identical. Yet,
    > clearly it's failing performing the cast.
    >
    > What's _really_ going on behind the scenes that explains why C# is
    > doing this?[/color]

    Because you haven't actually got an IFooBar. Just because it's got the
    same methods doesn't mean it's the same interface. Here's another
    example:

    public class Foo
    {
    }

    No extra fields, methods or anything else on top of what's provided by
    System.Object, right? But I can't do:

    object o = new object();
    Foo f = (Foo) o;

    - it fails at runtime, just like your example does.

    The runtime doesn't care about whether or not an instance meets all the
    requirements (in terms of members etc) to implement an interface - it
    cares whether the *actual type* of the object implements the interface.

    --
    Jon Skeet - <skeet@pobox.co m>
    http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
    If replying to the group, please do not mail me too

    Comment

    • Nicholas Paldino [.NET/C# MVP]

      #3
      Re: Interface Question

      Walt,

      The reason this doesn't work is because the identity of IFooBar is
      different from that of IFooBar. IFooBar extends IHTMLDocument2. However,
      when the Document property returns a value, it doesn't have any clue what
      IFooBar is, it only knows that it implements IHTMLDocument2. What would the
      other methods/properties on IFooBar do if you were allowed to make this
      cast? There is no way of defining it in the interface...

      Hope this helps.


      --
      - Nicholas Paldino [.NET/C# MVP]
      - mvp@spam.guard. caspershouse.co m

      <walt.stoneburn er@gmail.com> wrote in message
      news:1138131948 .709320.111310@ z14g2000cwz.goo glegroups.com.. .[color=blue]
      > Why does aliasing an interface fail at runtime?
      >
      > SAMPLE WORKING CODE
      > ...
      > IHTMLDocument2 doc = (IHTMLDocument2 ) browser.Documen t;
      > ...
      >
      > BROKEN CODE
      > public interface IFooBar : IHTMLDocument2 { }
      > ...
      > IFooBar doc = (IFooBar) browser.Documen t;
      > ...
      >
      > The broken code example compiles with no errors or warnings, but causes
      > an System.InvalidC astException exception at runtime, with a more
      > detailed message of "Specified cast is not valid."
      >
      > What I don't get is that if my IFooBar interface inheirts from an
      > interface that works and contains no other additional method
      > signatures, then in theory the interfaces should be identical. Yet,
      > clearly it's failing performing the cast.
      >
      > What's _really_ going on behind the scenes that explains why C# is
      > doing this?
      >
      > Thanks,
      > -Walt Stoneburner
      >[/color]


      Comment

      • walt.stoneburner@gmail.com

        #4
        Re: Interface Question

        I'm about 80% of the way to emotionally accepting the answer; I see
        where Jon Skeet was going, and intellectually accept what he pointed
        out.

        Here's my real problem: I've got a browser.Documen t object, and
        -three- different interfaces that it supports: IHTMLDocument,
        IHTMLDocument2, and IHTMLDocument3. .. each doing something different.

        I'm having to cast and maintain a reference to each flavor of
        interface, and this seems silly.

        I'd like to be able to just do this:
        public IMyDoc : IHTMLDocument, IHTMLDocument2, and IHTMLDocument3 { }

        ....and have IMyDoc provide all the interfaces combined that I'm going
        to use.

        If this isn't what the inheirtance-like syntax is for on the interface
        definition, what's problem is it solving? Why give us the ability to
        list base interfaces?

        (And that's where the remaining 20% of my confusion is coming from.)

        Thanks all,
        -wls

        Comment

        • walt.stoneburner@gmail.com

          #5
          Re: Interface Question

          I went back and read your's and Jon's posts again, trying to
          internalize them into a mental model that makes sense.

          Let me see if I'm getting closer...

          interface A : B, C { }

          This does NOT say that "A is an interface that is the conglomeration of
          B and C, feel free to cast to A and use any of the B and C
          interfaces..."

          Instead, it says "A is a unique interface and type under its own right,
          and it just happens to implement the same signatures as B and C -- so,
          feel free to cast a returned A interface into B, or even C, but you
          can't use A where B and C are used."

          ....am I any closer in my understanding?

          Comment

          • Stoitcho Goutsev \(100\)

            #6
            Re: Interface Question

            Walt,

            In addtion to what Jon and Nicholas said regarding the reason why it fails
            in run time, I want to try to explaing it doesn't fail at compile time.

            It doesn't fail at compile time because you give wrong instructions to the
            compiler.

            Using explicit cast tells the compiler that you know what you are doing and
            you guarantee that the cast is valid even thought it is not obvious.

            Re-write the line
            IFooBar doc = (IFooBar) browser.Documen t;

            to be

            IFooBar doc = browser.Documen t;
            (no explicit cast)

            Try to compile this code. The compiler will fire an error because this is
            what the compiler knows about the types. IFooBar is not the same as
            IHTMLDocument2 and the object returned by the browser.Documen t doesn't
            implement this new interface, it implements its base type. Cast from base to
            derived types is not valid in all of the cases, because derived types are
            more specialized and might have added new functionality to the base type.

            By using explicit cast you basically say - "Don't give me the error. I know
            what I'm doing and it is correct". That is OK, but not in this case.

            It would be OK if you new that the object returned by browser.Documen t
            implements IFooBar interface, but for some reason you received (via method
            parameter for example) reference to IHTMLDocument2.
            In this case the line

            IFooBar doc = obj;

            will give you the compile time error because you try to cast from base to
            more specialized type, but because you know that the cast is possible (the
            obj actually implements IFooBar) you can tell the compiler that you know
            that the cast is valid, so the compiler has to stop bothering you with that
            error message. You tell this using explicit cast:

            IFooBar doc = (IFooBar)obj;


            --
            HTH
            Stoitcho Goutsev (100)

            <walt.stoneburn er@gmail.com> wrote in message
            news:1138131948 .709320.111310@ z14g2000cwz.goo glegroups.com.. .[color=blue]
            > Why does aliasing an interface fail at runtime?
            >
            > SAMPLE WORKING CODE
            > ...
            > IHTMLDocument2 doc = (IHTMLDocument2 ) browser.Documen t;
            > ...
            >
            > BROKEN CODE
            > public interface IFooBar : IHTMLDocument2 { }
            > ...
            > IFooBar doc = (IFooBar) browser.Documen t;
            > ...
            >
            > The broken code example compiles with no errors or warnings, but causes
            > an System.InvalidC astException exception at runtime, with a more
            > detailed message of "Specified cast is not valid."
            >
            > What I don't get is that if my IFooBar interface inheirts from an
            > interface that works and contains no other additional method
            > signatures, then in theory the interfaces should be identical. Yet,
            > clearly it's failing performing the cast.
            >
            > What's _really_ going on behind the scenes that explains why C# is
            > doing this?
            >
            > Thanks,
            > -Walt Stoneburner
            >[/color]


            Comment

            • Jon Skeet [C# MVP]

              #7
              Re: Interface Question

              <walt.stoneburn er@gmail.com> wrote:[color=blue]
              > I'm about 80% of the way to emotionally accepting the answer; I see
              > where Jon Skeet was going, and intellectually accept what he pointed
              > out.
              >
              > Here's my real problem: I've got a browser.Documen t object, and
              > -three- different interfaces that it supports: IHTMLDocument,
              > IHTMLDocument2, and IHTMLDocument3. .. each doing something different.
              >
              > I'm having to cast and maintain a reference to each flavor of
              > interface, and this seems silly.
              >
              > I'd like to be able to just do this:
              > public IMyDoc : IHTMLDocument, IHTMLDocument2, and IHTMLDocument3 { }
              >
              > ...and have IMyDoc provide all the interfaces combined that I'm going
              > to use.[/color]

              I'm afraid that I haven't dealt with browser.Documen t myself, so it's
              hard to know the best way of managing the situation...
              [color=blue]
              > If this isn't what the inheirtance-like syntax is for on the interface
              > definition, what's problem is it solving? Why give us the ability to
              > list base interfaces?[/color]

              Two things:

              1) You can force anything which implements IDerivedInterfa ce to
              implement IBaseInterface in terms of the members it provides, without
              specifying them explicitly.

              2) It means you can always use something which you know implements
              IDerivedInterfa ce in cases which require IBaseInterface. For instance,
              if I have a method parameter of type IList, I can pass the value I'm
              given to another method which requires something of type IEnumerable,
              because anything which implements IList *must* implement IEnumerable
              anyway.

              --
              Jon Skeet - <skeet@pobox.co m>
              http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
              If replying to the group, please do not mail me too

              Comment

              • Jon Skeet [C# MVP]

                #8
                Re: Interface Question

                <walt.stoneburn er@gmail.com> wrote:[color=blue]
                > I went back and read your's and Jon's posts again, trying to
                > internalize them into a mental model that makes sense.
                >
                > Let me see if I'm getting closer...
                >
                > interface A : B, C { }
                >
                > This does NOT say that "A is an interface that is the conglomeration of
                > B and C, feel free to cast to A and use any of the B and C
                > interfaces..."
                >
                > Instead, it says "A is a unique interface and type under its own right,
                > and it just happens to implement the same signatures as B and C -- so,
                > feel free to cast a returned A interface into B, or even C, but you
                > can't use A where B and C are used."
                >
                > ...am I any closer in my understanding?[/color]

                Yes, I think so.

                --
                Jon Skeet - <skeet@pobox.co m>
                http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
                If replying to the group, please do not mail me too

                Comment

                • walt.stoneburner@gmail.com

                  #9
                  Re: Interface Question

                  Stoitcho,

                  Thank you. You've unwraveled a bigger portion of the mystery for me.
                  This makes total sense now, and I'm back happily coding.

                  Many thanks to everyone who provided clarification.
                  -wls

                  Comment

                  • Nicholas Paldino [.NET/C# MVP]

                    #10
                    Re: Interface Question

                    Walt,

                    In addition to what Jon said, I don't understand why you are trying to
                    create your own interface. I mean, you can't just derive from an interface,
                    and think that anything else that implements a ^part^ of the interface you
                    defined can support the whole definition.

                    --
                    - Nicholas Paldino [.NET/C# MVP]
                    - mvp@spam.guard. caspershouse.co m

                    <walt.stoneburn er@gmail.com> wrote in message
                    news:1138132925 .251729.28150@g 14g2000cwa.goog legroups.com...[color=blue]
                    > I'm about 80% of the way to emotionally accepting the answer; I see
                    > where Jon Skeet was going, and intellectually accept what he pointed
                    > out.
                    >
                    > Here's my real problem: I've got a browser.Documen t object, and
                    > -three- different interfaces that it supports: IHTMLDocument,
                    > IHTMLDocument2, and IHTMLDocument3. .. each doing something different.
                    >
                    > I'm having to cast and maintain a reference to each flavor of
                    > interface, and this seems silly.
                    >
                    > I'd like to be able to just do this:
                    > public IMyDoc : IHTMLDocument, IHTMLDocument2, and IHTMLDocument3 { }
                    >
                    > ...and have IMyDoc provide all the interfaces combined that I'm going
                    > to use.
                    >
                    > If this isn't what the inheirtance-like syntax is for on the interface
                    > definition, what's problem is it solving? Why give us the ability to
                    > list base interfaces?
                    >
                    > (And that's where the remaining 20% of my confusion is coming from.)
                    >
                    > Thanks all,
                    > -wls
                    >[/color]


                    Comment

                    Working...