Possible Duplicate:
Is it safe for structs to implement interfaces?
Take this code:
interface ISomeInterface
{
public int SomeProperty { get; }
}
struct SomeStruct : ISomeInterface
{
int someValue;
public int SomeProperty { get { return someValue; } }
public SomeStruct(int value)
{
someValue = value;
}
}
and then I do this somewhere:
ISomeInterface someVariable = new SomeStruct(2);
is the SomeStruct
boxed in this case?
The MSDN documentation tells us that structs are value, not reference types. They are boxed when converting to/from a variable of type
object
. But the central question here is: what about a variable of an interface type? Since the interface can also be implemented by a class, then this must be tantamount to converting from a value to a reference type, as Jon Skeet already said, therefore yes boxing would occur. More discussion on an msdn blog.Jon's point is true, but as a side note there is one slight exception to the rule; generics. If you have
where T : ISomeInterface
, then this is constrained, and uses a special opcode. This means the interface can be used without boxing. For example:This does not involve boxing, even for value-type
T
. However, if (in the sameFoo
) you do:then that boxes as before. The constrained only applies directly to
T
.Yes, it is. Basically whenever you need a reference and you've only got a value type value, the value is boxed.
Here,
ISomeInterface
is an interface, which is a reference type. Therefore the value ofsomeVariable
is always a reference, so the newly created struct value has to be boxed.I'm adding this to hopefully shed a little more light on the answers offered by Jon and Marc.
Consider this non-generic method:
Hmm... setting a
ref
parameter to null. That's only possibly for a reference type, correct? (Well, or for aNullable<T>
; but let's ignore that case to keep things simple.) So the fact that this method compiles tells us that a variable declared to be of some interface type must be treated as a reference type.The key phrase here is "declared as": consider this attempt to call the above method:
Granted, the reason you can't pass
x
in the above code toSetToNull
is thatx
would need to be declared as anISomeInterface
for you to be able to passref x
-- and not because the compiler magically knows thatSetToNull
includes the lineobj = null
. But in a way that just reinforces my point: theobj = null
line is legal precisely because it would be illegal to pass a variable not declared as anISomeInterface
to the method.In other words, if a variable is declared as an
ISomeInterface
, it can be set to null, pure and simple. And that's because interfaces are reference types -- hence, declaring an object as an interface and assigning it to a value type object boxes that value.Now, on the other hand, consider this hypothetical generic method: