I was just participating in Stack Overflow question Is everything in .NET an object?.
And one poster (in comments of accepted answer) seemed to think that p
I believe that calling ToString, Equals and Gethashcode result in boxing if the structure does not override the methods.
Here's the IL for your code:
L_0001: ldc.i4.5 // get a 5 on the stack
L_0002: stloc.0 // store into x
L_0003: ldloca.s x // get the address of x on the stack
L_0005: call instance string [mscorlib]System.Int32::ToString() // ToString
L_000a: stloc.1 // store in s
So the answer in this case is no.
@ggf31316
"I believe that calling ToString, Equals and Gethashcode result in boxing if the structure does not override the methods."
I have checked ToString for you. Int32 does override ToString, so I made a struct that doesn't. I used .NET Reflector to ensure that the struct wasn't somehow magically overriding ToString(), and it wasn't.
So the code was like this:
using System;
namespace ConsoleApplication29
{
class Program
{
static void Main(string[] args)
{
MyStruct ms = new MyStruct(5);
string s = ms.ToString();
Console.WriteLine(s);
}
}
struct MyStruct
{
private int m_SomeInt;
public MyStruct(int someInt)
{
m_SomeInt = someInt;
}
public int SomeInt
{
get
{
return m_SomeInt;
}
}
}
}
And the MSIL (via ILDASM) for the Main method is this:
IL_0000: ldloca.s ms
IL_0002: ldc.i4.5
IL_0003: call instance void ConsoleApplication29.MyStruct::.ctor(int32)
IL_0008: ldloca.s ms
IL_000a: constrained. ConsoleApplication29.MyStruct
IL_0010: callvirt instance string [mscorlib]System.Object::ToString()
IL_0015: stloc.1
IL_0016: ldloc.1
IL_0017: call void [mscorlib]System.Console::WriteLine(string)
IL_001c: ret
Now, despite no boxing call taking place, if you check the documentation about a constrained + a call virt, you will find it states that boxing DOES take place. oOo
Quote:
If thisType is a value type and thisType does not implement method then ptr is dereferenced, boxed, and passed as the 'this' pointer to the callvirt method instruction.
In the case you have given the answer is no, as plinth pointed out.
However, it will if you call a method through an interface pointer.
Consider the code:
interface IZot
{
int F();
}
struct Zot : IZot
{
public int F()
{
return 123;
}
}
Then
Zot z = new Zot();
z.F();
Does not result in boxing:
.locals init (
[0] valuetype ConsoleApplication1.Zot z)
L_0000: nop
L_0001: ldloca.s z
L_0003: initobj ConsoleApplication1.Zot
L_0009: ldloca.s z
L_000b: call instance int32 ConsoleApplication1.Zot::F()
L_0010: pop
L_0011: ret
However, this does:
IZot z = new Zot();
z.F();
.locals init (
[0] class ConsoleApplication1.IZot z,
[1] valuetype ConsoleApplication1.Zot CS$0$0000)
L_0000: nop
L_0001: ldloca.s CS$0$0000
L_0003: initobj ConsoleApplication1.Zot
L_0009: ldloc.1
L_000a: box ConsoleApplication1.Zot
L_000f: stloc.0
L_0010: ldloc.0
L_0011: callvirt instance int32 ConsoleApplication1.IZot::F()
L_0016: pop