sizeof(char) vs SizeOf(char)

May 6, 2008 22:59 by Andre Loker

This is weird.

   1: using System;
   2: using System.Runtime.InteropServices;
   3:  
   4: public class Program {
   5:     public static void Main() {
   6:         Console.Out.WriteLine("sizeof(char) = {0}", sizeof (char));
   7:         Console.Out.WriteLine("Marshal.SizeOf(typeof(char)) = {0}", Marshal.SizeOf(typeof(char)));
   8:     }
   9: }

 

Output:

   1: sizeof(char) = 2
   2: Marshal.SizeOf(typeof(char)) = 1

And here is why: Of course Marshal.SizeOf handles different character sets when strings fields in structures are marshalled. An interesting point is that when no character set is explicitly given, the CLR assumes CharSet.Ansi. As System.Char has no CharSet defined, SizeOf calculates the marshalled size assuming Ansi encoding. When the char is within a struct, the StructLayoutAttribute can be used and is honoured by SizeOf:

   1: using System;
   2: using System.Runtime.InteropServices;
   3:  
   4: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
   5: public struct Ex1 {
   6:     private char x;
   7: }
   8:  
   9: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
  10: public struct Ex2 {
  11:     private char x;
  12: }
  13:  
  14: public class Program {
  15:  
  16:     public static unsafe void Main() {
  17:         Console.Out.WriteLine("sizeof(Ex1) = {0}", sizeof (Ex1));
  18:         Console.Out.WriteLine("Marshal.SizeOf(typeof(Ex1)) = {0}", Marshal.SizeOf(typeof (Ex1)));
  19:         Console.Out.WriteLine("sizeof(Ex2) = {0}", sizeof (Ex2));
  20:         Console.Out.WriteLine("Marshal.SizeOf(typeof(Ex2)) = {0}", Marshal.SizeOf(typeof (Ex2)));
  21:     }
  22: }
   1: sizeof(Ex1) = 2
   2: Marshal.SizeOf(typeof(Ex1)) = 1
   3: sizeof(Ex2) = 2
   4: Marshal.SizeOf(typeof(Ex2)) = 2

This looks more realistic again. sizeof(Ex1) both return the same size the structs occupy in memory (which is 2 bytes because of the unicode character). Marshal.SizeOf(typeof(Ex1)) return the marshalled size, which is 1 because I chose Ansi as the character set. Similarly, the marshalled size of Ex2 is 2 because of the unicode character set.


Where T : Enum?

April 17, 2008 18:13 by Andre Loker

Mir ist nicht klar, warum C# bei den Constraints von generischen Typen und Methoden manchmal so pingelig ist, obwohl die CLR die entsprechenden Constraints erlaubt.

Beispiel: folgender Code ist in C# nicht kompilierbar

   1: class X {
   2:     public void MachWas<T>(T foo) where T : Enum {
   3:     }
   4: }

error CS0702: Constraint cannot be special class 'System.Enum'

In C++/CLI kein Problem:

   1: ref class X {
   2:     generic<typename T> where T : System::Enum
   3:     void MachWas( T foo) {
   4:     }
   5: };