views:

1933

answers:

6

I have a C# interface with certain method parameters declared as object types. However, the actual type passed around can differ depending on the class implementing the interface:

public interface IMyInterface
{
    void MyMethod(object arg);
}

public class MyClass1 : IMyInterface
{
    public void MyMethod(object arg)
    {
        MyObject obj = (MyObject) arg;
        // do something with obj...
    }
}

public class MyClass2 : IMyInterface
{
    public void MyMethod(object arg)
    {
        byte[] obj = (byte[]) arg;
        // do something with obj...
    }
}

The problem with MyClass2 is that the conversion of byte[] to and from object is boxing and unboxing, which are computationally expensive operations affecting performance.

Would solving this problem with a generic interface avoid boxing/unboxing?

public interface IMyInterface<T>
{
    void MyMethod(T arg);
}

public class MyClass1 : IMyInterface<MyObject>
{
    public void MyMethod(MyObject arg)
    {
        // typecast no longer necessary
        //MyObject obj = (MyObject) arg;
        // do something with arg...
    }
}

public class MyClass2 : IMyInterface<byte[]>
{
    public void MyMethod(byte[] arg)
    {
        // typecast no longer necessary
        //byte[] obj = (byte[]) arg;
        // do something with arg...
    }
}

How is this implemented in .NET vs Mono? Will there be any performance implications on either platform?

Thank you!

+8  A: 

The problem with MyClass2 is that the conversion of byte[] to and from object is boxing and unboxing, which are computationally expensive operations affecting performance.

There is no boxing involved with array types, even one with value type elements. An array is a reference type.

The overhead on (byte[]) arg is minimal at best.

leppie
This is a good point. It occurred to me while I was typing up the question, but somehow it slipped my mind to ask...
Mike Mazur
But boxing is only applicable to reference types. It is when I go from a specific reference type to its generic object interface and back that I box/unbox.
j0rd4n
No, un/boxing only occurs with value types.
leppie
Whoops - I stand corrected. You are correct. http://msdn.microsoft.com/en-us/library/yz2be5wk.aspx
j0rd4n
+1  A: 

I can't speak to Mono, but using a generic interface should solve the boxing/unboxing issue in the MS runtime.

Joel Coehoorn
There is no boxing involved here.
leppie
No, but there _could_ be for other types with the non-generic implementation.
Joel Coehoorn
+6  A: 

I'm not sure how it is implemented in mono, but generic interfaces will help because the compiler creates a new function of the specific type for each different type used (internally, there are a few cases where it can utilize the same generated function). If a function of the specific type is generated, there is no need to box/unbox the type.

This is why the Collections.Generic library was a big hit at .NET 2.0 because collections no longer required boxing and became significantly more efficient.

j0rd4n
+12  A: 

You will get the same benefits in Mono that you do in .NET.

We strongly recommend that you use Mono 1.9 or Mono 2.0 RCx in general, as generics support only matured with 1.9.

miguel.de.icaza
Good work on Mono 1.9! I have IronScheme running and working almost as good as on MS, only a few minor issues with Encoding returning empty string :)
leppie
Oh, and tail calls seem to be not working!
leppie
Wow. Its the Man behind Mono. And his rep is CRAP compared to mine! I'M FRIGGEN AWESOME!
Will
leppie, those are great news! I am looking forward to try out IronScheme!
miguel.de.icaza
Regards, Miguel! :)
Andrei Rinea
A: 

Yes, in .Net (MS not sure about mono) generics are implemented at compile time so there is no boxing or unboxing going on at all. Contrast to java generics which are syntactic sugar that just perform the casts for you in the background (at least it was this way once). The main problem with generics is you can't treat generic containers polymorphically, but that is a bit off your topic :-)

Phil Bennett
A: 

Given you're using a recent version of mono, 2.0 if you can.

Generic interface performance on Mono is very good, on pair with regular interface dispatch.

Dispatch of generic virtual methods[1] is terrible on all released versions of mono, it has improved in 1.9 thou.

The problem is not that bad as the performance issue with generic virtual methods has been fixed for the next release of mono (2.2), which is scheduled to the end of this year.

[1] A generic virtual method is something like:

public interface Foo {

  void Bla<T> (T a, T b);

}