3

First part:

I have a string...

string sTest = "This is my test string";

How can I (manually, without code) determine the SizeOf the string? What should it end up being? How do you get that size?


Second Part:

I have a class...

[StructLayout(LayoutKind.Sequential)]
public class TestStruct
{
    public string Test;
}

I use it...

TestStruct oTest = new TestStruct();
oTest.Test = "This is my test string";

Are there any differences in size from the first part to the second part?


Update:

The point of this is to use the size as a way to create a memory map file.

long lMapSize = System.Runtime.InteropServices.Marshal.SizeOf(oTest);
mmf = MemoryMappedFile.CreateOrOpen("testmap", lMapSize);

Just thought it was worth noting. Currently lMapSize = 4. Which confuses the ... out of me! Thanks everyone!

Arvo Bowen
  • 4,524
  • 6
  • 51
  • 109
  • 1
    The details of how the size is calculated are given in the following answer - http://stackoverflow.com/questions/207592/getting-the-size-of-a-field-in-bytes-with-c-sharp – codelion Aug 05 '14 at 01:13
  • 1) There are 6 answers, 2) None of the answers answer my question specifically. I want to know how to do it manually, not with code. – Arvo Bowen Aug 05 '14 at 01:27
  • From the first answer by Jon Skeet - You can't, basically. It will depend on padding, which may well be based on the CLR version you're using and the processor etc. – codelion Aug 05 '14 at 01:32
  • @ArvoBowen - there are couple answers showing how to compute size and what additional fields are. You may want to carefully read [How the CLR Creates Runtime Objects](http://msdn.microsoft.com/en-us/magazine/cc163791.aspx) article on MSDN if you want deep details. Note that answer to second question depends on whether you are asking them for same program or 2 different once due to compile time interning. – Alexei Levenkov Aug 05 '14 at 02:09
  • @Alexei They would be compiled at the same time as a solution with multi projects, same time, same cpu, same specs, etc... – Arvo Bowen Aug 05 '14 at 02:20
  • 2
    `System.Runtime.InteropServices.Marshal.SizeOf` returned you size of oTest, which is pointer to reference type `TestStruct`. 4 bytes is 32 bit. But even if `TestStruct` was value type result would be 4 as well since `TestStruct` has only one reference field. – Atomosk Aug 05 '14 at 02:53
  • Based on your edit it looks like you'd be better off doing proper serialization (maybe `BinaryFormater` is enough for your)... Side note: please try not to name reference type (`class`) as `XxxxStruct` to avoid confusion on what it actually is. – Alexei Levenkov Aug 05 '14 at 22:13
  • Thanks for the advice Alexei, yea the naming was back when I was using a struct... I changed it to a class in the middle of writing this question for another reason... I'm very anal retentive about my naming scheme... ;) – Arvo Bowen Aug 06 '14 at 03:08

1 Answers1

2

string is a reference type, so field inside other class or struct or local method variable will be a pointer - IntPtr. Size of pointer is 32 bit on 32 bit pc and 64 for 64.
If you want to know size of string itself, you need to know which encoding you are going to use. Encoding.UTF8.GetByteCount("aaa") will return size of "aaa" in UTF8 encoding. But this will return only size of string, not .net object size.
Looks like there is no accurate way to calculate size of object from code. If you want to know what's going on in your application there is some memory profilers for it, just search 'C# memory profiler'. I've used only mono profiler with heap-shot, so I can't recomend you which of profilers is good.
Another way is to use WinDBG with sos.dll and sosex.dll. Here you can find example of using sos.dll.


Update:
You can also serialize your object into byte array. Serializer will add some extra data like assembly name and version.
byte[] bytes;
using (MemoryStream stream = new MemoryStream())
{
    IFormatter formatter = new BinaryFormatter();
    formatter.Serialize(stream, myObject);
    bytes = stream.ToArray();
}

using (MemoryStream stream = new MemoryStream(bytes))
{
    IFormatter formatter = new BinaryFormatter();
    myObject = formatter.Deserialize(stream);
}
Community
  • 1
  • 1
Atomosk
  • 1,871
  • 2
  • 22
  • 26
  • So the "data" I pass into the MemoryMapFile... Is that supposed to be actual data or just pointers to memory? If I get 4 bytes for my class that contains 1 object (string), or get 8 bytes for my class that contains 2 objects (string and int), those are just the size of the pointers right? Should I create a MemoryMapFile to hold the pointers and let my apps talk by passing pointers? Or pass actual data? – Arvo Bowen Aug 05 '14 at 04:21
  • @ArvoBowen There is no sense in storing pointers, GC moves objects when it collects garbage and refreshes all pointers value. Stored values will not refresh, so they will have wrong values. For your particular task, I'd convert string to char array `"aaa".ToCharArray()`. Size of char is 2 bytes - `sizeof(char)`. So size of array of chars should be twice array lenght - `sizeof(char) * array.Lenght`. Then you can store array of chars to MemoryMappedFile. – Atomosk Aug 05 '14 at 04:31
  • Thanks Atomosk, but the problem is a little bigger than that. I would not know the size of the class or how many objects it might contain, or what type of objects are in it. I need a way to calculate the size of the entire class. Is that at all possible? – Arvo Bowen Aug 05 '14 at 05:06
  • @ArvoBowen It is possible, every serializer does that via reflection, but I'm not sure if there is any solution for serializing to `MemoryMapFile`, which looks like it can keep only `struct` types. I wonder why can't you simply serialize your object with binary, xml or json serializer? – Atomosk Aug 05 '14 at 05:41
  • OK that sounds promising... Is it possible for you to update your answer and add an example turning my class or a struct into binary data and then back again from binary data to a class or struct? – Arvo Bowen Aug 05 '14 at 06:26
  • This seems to be the best approach. Serializing the class (turning it into a byte array) first and then getting the size seems like the best way to go about it. That way there is no doubt how many bytes need to be reserved for the memory map file. Thanks so much for the answer! – Arvo Bowen Aug 05 '14 at 16:41