Declaring a Constructor in an Interface?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Ignacio Machin \( .NET/ C#  MVP \)

    #16
    Re: Declaring a Constructor in an Interface?

    Hi,

    [color=blue]
    > I have always believed interfaces were superior to abstract classes.
    > I apologie for the misleading information i might have given.[/color]

    They are two different things, an abstract typemay define some
    functionality and let other to be defined by the derived type, an interface
    dictate the methods/properties a type MUST implement.

    Of course the class define an interface implicitely , IIRC there was a
    programming language where you had to explicitly define the interface of a
    type, but I may be wrong :)

    Cheers,

    --
    Ignacio Machin,
    ignacio.machin AT dot.state.fl.us
    Florida Department Of Transportation


    Comment

    • Dennis Myrén

      #17
      Re: Declaring a Constructor in an Interface?

      Thank you mr. Machin.

      I learned something today!

      --
      Regards,
      Dennis JD Myrén
      Oslo Kodebureau
      "Ignacio Machin ( .NET/ C# MVP )" <ignacio.mach in AT dot.state.fl.us > wrote
      in message news:uywKGPymEH A.2616@tk2msftn gp13.phx.gbl...[color=blue]
      > Hi,
      >
      >[color=green]
      > > I have always believed interfaces were superior to abstract classes.
      > > I apologie for the misleading information i might have given.[/color]
      >
      > They are two different things, an abstract typemay define some
      > functionality and let other to be defined by the derived type, an[/color]
      interface[color=blue]
      > dictate the methods/properties a type MUST implement.
      >
      > Of course the class define an interface implicitely , IIRC there was a
      > programming language where you had to explicitly define the interface of a
      > type, but I may be wrong :)
      >
      > Cheers,
      >
      > --
      > Ignacio Machin,
      > ignacio.machin AT dot.state.fl.us
      > Florida Department Of Transportation
      >
      >[/color]


      Comment

      • Ian Griffiths [C# MVP]

        #18
        Re: Declaring a Constructor in an Interface?

        Dennis Myrén wrote:[color=blue]
        >
        > Therefore, i decided to modify your test program slightly
        > to better match my current project.
        >
        > I changed:
        > static void SpeedTestInterf ace(IFoo obj)
        > into:
        > static void SpeedTestInterf ace(InterfaceIm pl obj)
        > and also:
        > static void SpeedTestABC(AB C obj)
        > into:
        > static void SpeedTestABC(Co ncreteDerived obj)
        >
        > Somewhat interesting(to me anyway) was that the interface approach
        > went a lot faster.[/color]

        Have a look at the IL. Before your change, the way that SpeedTestInterf ace
        calls the method is:

        callvirt instance void IFoo::SayHello( )

        but after your change, it looks like this:

        callvirt instance void InterfaceImpl:: SayHello()

        And don't be misled by that 'callvirt' - the 'virt' part doesn't mean what
        you might thing. The thing that determines whether virtual, interface, or
        basic method dispatch gets used is the nature of the target method.

        In the first case, it's calling IFoo.SayHello. And since that's an interface
        method, it will be using interface-style dispatch.

        But in the second case, notice that it has completely ignored the interface.
        (Indeed, you can modify the InterfaceImpl class so that it no longer claims
        to implement IFoo without changing the behaviour.) The compiler has done
        this because your program no longer relies on the InterfaceImpl class
        implementing IFoo. It's just calling the public SayHello method directly.
        This is why you get the same performance as you would with any other direct
        method call - you really aren't using interfaces in this case. You're
        calling a public method. It so happens that the public method is also
        available via an interface, but you're not exploiting that here. (As is
        easily proved by the fact that removing the interface from the list that
        InterfaceImpl implements doesn't stop your version of the program from
        working.)

        This only works because you made SayHello public. So it's not just there to
        implement the IFoo interface, it's also a part of InterfaceImpl's public
        face in its own right. It would be different if you had done this:

        public class InterfaceImpl : IFoo
        {
        void IFoo.SayHello() { }
        }

        This C# syntax says that this method is the implementation of IFoo.SayHello,
        but is *not* part of the class's public API. You'll find that if you do
        this, your modified version of the test won't work. You'll have to go back
        to what I wrote, and it will of course run slower again.


        [color=blue]
        >This is my most average results running your test with no modification:
        >Non-virtual: 103,63 million calls per second
        >ABC: 104,47 million calls per second
        >Interface: 81,98 million calls per second[/color]

        Now that's interesting. Are these really the results you got with the code
        exactly as I posted it?

        It's interesting because you're getting very different results from me.
        (Obviously the results are different partly because we have different
        hardware. But what's interesting is the relative differences beween each
        type of call.) I get this:

        Non-virtual: 510.16 million calls per second
        ABC: 170.31 million calls per second
        Interface: 155.36 million calls per second

        So my non-virtual calls are way faster than the other two. You're finding
        the non-virtual runs about the same speed as the ABC calls, which is
        completely different from what I got. (So it looks almost as though your
        non-virtual case has been slowed down to run at the same speed as the
        virtual call.)

        So, four questions:

        1) Is that definitely the results from the code I posted with no mods at
        all?
        2) Did you let the test run to completion? The first set of results will
        probably be bogus due to JIT compilation transient timing issues. You want
        to ignore the first three results and look at the rest it prints out.
        3) What version of the .NET framework are you running this on?
        4) Are you running in the debugger?
        [color=blue]
        > And this is my most average results running your test with those
        > modifications:
        > Non-virtual: 104,16 million calls per second
        > ABC: 103,93 million calls per second
        > Interface: 102,7 million calls per second
        >
        > Is there a logical explanation for that speed enhancement?[/color]

        Yes - the case labelled as "Interface" is no longer really using interfaces
        for the reasons described above. But again, your figures look different from
        mine. I get this kind of thing with your modifications:

        Non-virtual: 512.36 million calls per second
        ABC: 172.32 million calls per second
        Interface: 515.27 million calls per second

        So these are figures that makes sense to me, because with your modifications
        to the test, the so-called 'Interface' case isn't using interfaces any more.
        It's making a direct call on a method which happens also to be available via
        an interface which the code is choosing not to use. So as you'd expect,
        it's running at about the same speed as the other 'non-virtual' case. (Give
        or take a few percent, which will just be experimental error.)

        What I don't understand is why in both your 'before' and 'after' cases, the
        ABC case runs roughly as fast as the direct call. I wouldn't expect it to,
        and on my system it definitely doesn't! So I'm trying to understand what's
        different about your setup and mine.

        If you are running in the debugger, try running outside instead. I just
        compiled and ran it from the command line.


        --
        Ian Griffiths - http://www.interact-sw.co.uk/iangblog/
        DevelopMentor - http://www.develop.com/


        Comment

        • Dennis Myrén

          #19
          Re: Declaring a Constructor in an Interface?

          Thanks for the help once again mr. Griffiths.

          Yes, I also noticed the strange differences when running your test
          and comparing the results to those that you got.
          [color=blue]
          >1) Is that definitely the results from
          >the code I posted with no mods at all?[/color]
          Yes, it is! Very strange indeed.
          [color=blue]
          >2) Did you let the test run to completion? The first set of results will
          >probably be bogus due to JIT compilation transient timing issues. You want
          >to ignore the first three results and look at the rest it prints out.[/color]
          Yes, i looped five times, and i also repeated the execution of the program 3
          times.
          I will run once again now, and paste the exact output at the end of this
          post
          (using your code, absolutely unmodified).
          [color=blue]
          >3) What version of the .NET framework are you running this on?[/color]
          I am running .NET Framework v1.1.4322.
          [color=blue]
          >4) Are you running in the debugger?[/color]
          Yes, i am running in debug mode from Visual Studio .NET Version 7.1.3088.

          INFORMATION ABOUT MY SYSTEM:
          Acer Laptop Machine, Intel Pentium M Processor 1700 MHz, 512 MB of RAM
          running Windows XP Professional Version 2002 Service Pack 1


          EXACT PROGRAM EXECUTION OUTPUT:
          Non-virtual: 111,6 million calls per second
          ABC: 108,73 million calls per second
          Interface: 98,14 million calls per second
          Non-virtual: 110,41 million calls per second
          ABC: 110,83 million calls per second
          Interface: 96,91 million calls per second
          Non-virtual: 106,86 million calls per second
          ABC: 110,19 million calls per second
          Interface: 97,58 million calls per second
          Non-virtual: 110,26 million calls per second
          ABC: 108,95 million calls per second
          Interface: 98,58 million calls per second
          Non-virtual: 108,77 million calls per second
          ABC: 102,65 million calls per second
          Interface: 91,38 million calls per second


          Hmm what is wrong with my system.

          --
          Regards,
          Dennis JD Myrén
          Oslo Kodebureau
          "Ian Griffiths [C# MVP]" <ian-interact-sw@nospam.nospa m> wrote in message
          news:ewkoz7ymEH A.3684@TK2MSFTN GP12.phx.gbl...[color=blue]
          > Dennis Myrén wrote:[color=green]
          > >
          > > Therefore, i decided to modify your test program slightly
          > > to better match my current project.
          > >
          > > I changed:
          > > static void SpeedTestInterf ace(IFoo obj)
          > > into:
          > > static void SpeedTestInterf ace(InterfaceIm pl obj)
          > > and also:
          > > static void SpeedTestABC(AB C obj)
          > > into:
          > > static void SpeedTestABC(Co ncreteDerived obj)
          > >
          > > Somewhat interesting(to me anyway) was that the interface approach
          > > went a lot faster.[/color]
          >
          > Have a look at the IL. Before your change, the way that[/color]
          SpeedTestInterf ace[color=blue]
          > calls the method is:
          >
          > callvirt instance void IFoo::SayHello( )
          >
          > but after your change, it looks like this:
          >
          > callvirt instance void InterfaceImpl:: SayHello()
          >
          > And don't be misled by that 'callvirt' - the 'virt' part doesn't mean what
          > you might thing. The thing that determines whether virtual, interface, or
          > basic method dispatch gets used is the nature of the target method.
          >
          > In the first case, it's calling IFoo.SayHello. And since that's an[/color]
          interface[color=blue]
          > method, it will be using interface-style dispatch.
          >
          > But in the second case, notice that it has completely ignored the[/color]
          interface.[color=blue]
          > (Indeed, you can modify the InterfaceImpl class so that it no longer[/color]
          claims[color=blue]
          > to implement IFoo without changing the behaviour.) The compiler has done
          > this because your program no longer relies on the InterfaceImpl class
          > implementing IFoo. It's just calling the public SayHello method directly.
          > This is why you get the same performance as you would with any other[/color]
          direct[color=blue]
          > method call - you really aren't using interfaces in this case. You're
          > calling a public method. It so happens that the public method is also
          > available via an interface, but you're not exploiting that here. (As is
          > easily proved by the fact that removing the interface from the list that
          > InterfaceImpl implements doesn't stop your version of the program from
          > working.)
          >
          > This only works because you made SayHello public. So it's not just there[/color]
          to[color=blue]
          > implement the IFoo interface, it's also a part of InterfaceImpl's public
          > face in its own right. It would be different if you had done this:
          >
          > public class InterfaceImpl : IFoo
          > {
          > void IFoo.SayHello() { }
          > }
          >
          > This C# syntax says that this method is the implementation of[/color]
          IFoo.SayHello,[color=blue]
          > but is *not* part of the class's public API. You'll find that if you do
          > this, your modified version of the test won't work. You'll have to go back
          > to what I wrote, and it will of course run slower again.
          >
          >
          >[color=green]
          > >This is my most average results running your test with no modification:
          > >Non-virtual: 103,63 million calls per second
          > >ABC: 104,47 million calls per second
          > >Interface: 81,98 million calls per second[/color]
          >
          > Now that's interesting. Are these really the results you got with the[/color]
          code[color=blue]
          > exactly as I posted it?
          >
          > It's interesting because you're getting very different results from me.
          > (Obviously the results are different partly because we have different
          > hardware. But what's interesting is the relative differences beween each
          > type of call.) I get this:
          >
          > Non-virtual: 510.16 million calls per second
          > ABC: 170.31 million calls per second
          > Interface: 155.36 million calls per second
          >
          > So my non-virtual calls are way faster than the other two. You're finding
          > the non-virtual runs about the same speed as the ABC calls, which is
          > completely different from what I got. (So it looks almost as though your
          > non-virtual case has been slowed down to run at the same speed as the
          > virtual call.)
          >
          > So, four questions:
          >
          > 1) Is that definitely the results from the code I posted with no mods at
          > all?
          > 2) Did you let the test run to completion? The first set of results will
          > probably be bogus due to JIT compilation transient timing issues. You[/color]
          want[color=blue]
          > to ignore the first three results and look at the rest it prints out.
          > 3) What version of the .NET framework are you running this on?
          > 4) Are you running in the debugger?
          >[color=green]
          > > And this is my most average results running your test with those
          > > modifications:
          > > Non-virtual: 104,16 million calls per second
          > > ABC: 103,93 million calls per second
          > > Interface: 102,7 million calls per second
          > >
          > > Is there a logical explanation for that speed enhancement?[/color]
          >
          > Yes - the case labelled as "Interface" is no longer really using[/color]
          interfaces[color=blue]
          > for the reasons described above. But again, your figures look different[/color]
          from[color=blue]
          > mine. I get this kind of thing with your modifications:
          >
          > Non-virtual: 512.36 million calls per second
          > ABC: 172.32 million calls per second
          > Interface: 515.27 million calls per second
          >
          > So these are figures that makes sense to me, because with your[/color]
          modifications[color=blue]
          > to the test, the so-called 'Interface' case isn't using interfaces any[/color]
          more.[color=blue]
          > It's making a direct call on a method which happens also to be available[/color]
          via[color=blue]
          > an interface which the code is choosing not to use. So as you'd expect,
          > it's running at about the same speed as the other 'non-virtual' case.[/color]
          (Give[color=blue]
          > or take a few percent, which will just be experimental error.)
          >
          > What I don't understand is why in both your 'before' and 'after' cases,[/color]
          the[color=blue]
          > ABC case runs roughly as fast as the direct call. I wouldn't expect it[/color]
          to,[color=blue]
          > and on my system it definitely doesn't! So I'm trying to understand[/color]
          what's[color=blue]
          > different about your setup and mine.
          >
          > If you are running in the debugger, try running outside instead. I just
          > compiled and ran it from the command line.
          >
          >
          > --
          > Ian Griffiths - http://www.interact-sw.co.uk/iangblog/
          > DevelopMentor - http://www.develop.com/
          >
          >[/color]


          Comment

          • Ian Griffiths [C# MVP]

            #20
            Re: Declaring a Constructor in an Interface?

            Dennis Myrén wrote:[color=blue][color=green]
            >>4) Are you running in the debugger?[/color]
            > Yes, i am running in debug mode from Visual Studio .NET
            > Version 7.1.3088.[/color]

            OK, it's a debug thing.

            I get the same results as you when I run in the debugger. (And not just
            relative speeds - I get more or less exactly the same figures, which is
            hardly surprising given how similar our systems are.)

            [color=blue]
            > Hmm what is wrong with my system.[/color]


            Nothing. Compile for Release mode and run outside the debugger, and you
            should see the same results as me.

            I'm not quite sure why building for Debug mode is doing this, but I know the
            JIT compiler generates different code when the code is compiled for Debug
            mode. It'll disable inlining I expect, which may account for most of the
            difference. The results are still a little surprising, nonetheless. But
            perf tends to go out of the window in debug builds, so it's wise not to use
            that to do any kind of perf tests...


            --
            Ian Griffiths - http://www.interact-sw.co.uk/iangblog/
            DevelopMentor - http://www.develop.com/


            Comment

            • Dennis Myrén

              #21
              Re: Declaring a Constructor in an Interface?

              Hi.

              Yes, as I switched to RELEASE mode my results went similar to your results.
              [color=blue]
              >But perf tends to go out of the window in debug builds,
              >so it's wise not to use that to do any kind of perf tests...[/color]
              Indeed. It is just, i assumed that was what you were doing.

              Thank you for your help.

              --
              Regards,
              Dennis JD Myrén
              Oslo Kodebureau
              "Ian Griffiths [C# MVP]" <ian-interact-sw@nospam.nospa m> wrote in message
              news:%23iabNpzm EHA.644@tk2msft ngp13.phx.gbl.. .[color=blue]
              > Dennis Myrén wrote:[color=green][color=darkred]
              > >>4) Are you running in the debugger?[/color]
              > > Yes, i am running in debug mode from Visual Studio .NET
              > > Version 7.1.3088.[/color]
              >
              > OK, it's a debug thing.
              >
              > I get the same results as you when I run in the debugger. (And not just
              > relative speeds - I get more or less exactly the same figures, which is
              > hardly surprising given how similar our systems are.)
              >
              >[color=green]
              > > Hmm what is wrong with my system.[/color]
              >
              >
              > Nothing. Compile for Release mode and run outside the debugger, and you
              > should see the same results as me.
              >
              > I'm not quite sure why building for Debug mode is doing this, but I know[/color]
              the[color=blue]
              > JIT compiler generates different code when the code is compiled for Debug
              > mode. It'll disable inlining I expect, which may account for most of the
              > difference. The results are still a little surprising, nonetheless. But
              > perf tends to go out of the window in debug builds, so it's wise not to[/color]
              use[color=blue]
              > that to do any kind of perf tests...
              >
              >
              > --
              > Ian Griffiths - http://www.interact-sw.co.uk/iangblog/
              > DevelopMentor - http://www.develop.com/
              >
              >[/color]


              Comment

              Working...