2

Consider the following scenario:

int Caller1<T>(T t) where T : IInterface {...}
T Caller2<T>() where T : IInterface {...}

class Wrappee // doesn't implement IInterface, but could

??? Wrapper : IInterface {
  private readonly Wrappee _wrappee;

  // methods call _wrappee's methods
}

Now, the general advice for choosing between struct and class is "use struct if you need value semantics and class for reference semantics". The semantics we need is "reference to Wrappee". But it seems we can still make Wrapper a struct: copying its value is the same is the same as copying a Wrappee reference, and the copies will have a reference to the same object! Overhead is lower and scalar replacement may be able to reduce it to zero for local variables. It seems all right to call even mutating methods on _wrappee.

Am I missing anything? Is there a good reason to make Wrapper a class instead?

There is one if the caller isn't generic:

int Caller(IInterface t) {...}

In this case Wrapper should be a class to avoid boxing.

Remark for those who know Haskell: I am trying to find the closest .NET analogue to newtype.

UPDATE: See Professional .NET 2.0 Generics and Peter Ritchie on MSDN forums for absence of boxing in the first case.

1
  • Why do you think using a struct as a generic type parameter would make a difference for the need for boxing? Commented Jul 31, 2009 at 18:13

3 Answers 3

4

Yes, since you will access wrapper via an IInterface variable, to avoid boxing, it should be a class.

EDIT: If you access wrapper via a variable typed as Wrapper, and access Wrapper methods, not IInterface methods, then a struct is fine.

Sign up to request clarification or add additional context in comments.

2 Comments

I don't access it via an IInterface variable, but a generic parameter constrained to derive from IInterface. See the update.
That is, calling code looks like: Wrapper y = Caller2(); return Caller1(y);
2

Often your class/struct will be stored or passed on internally by methods you call (you didn't show what Caller1 and Caller2 do), and in that case it will probably get boxed. Possibly more often than you expected. So unless you can prove that a struct is going to be way more efficient: don't bother and just stick with a class.

Besides, structs are often frowned upon unless they represent something like a data type, so chosing a class might prevent future discussions of a different nature.

However, if performance is really a concern, and if you can guarantee that instances are only passed as a parameter with a generic type constraint, and never stored in interface-typed fields or collections, the current inlining of structs by the .NET runtime will be more efficient, as your wrapper-struct will mostly be optimized away. But that's a lot of ifs.

Comments

0

I'd say class, because you're encapsulating behavior, not just data.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.