C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
Main: The program begins in Main. Here the Box is created with "new" and Open() is called, printing a message with Console.WriteLine.
ConsoleC# program that uses class
class Box
{
public void Open()
{
System.Console.WriteLine("Box opened");
}
}
class Program
{
static void Main()
{
// The program begins here.
// ... Create a new Box and call Open on it.
Box box = new Box();
box.Open();
}
}
Output
Box opened
Class B: This class is enclosed inside the declaration of class A. Class B is thus a nested class.
Public: Because it has a public accessibility modifier, class B can be accessed in places other than class A's scope.
Here: We create an instance of A and an instance of A.B. The instance of A does not contain an instance of B.
C# program that shows nested class
class A
{
public int _v1;
public class B
{
public int _v2;
}
}
class Program
{
static void Main()
{
A a = new A();
a._v1++;
A.B ab = new A.B();
ab._v2++;
}
}
Here: I test how effectively the C# compiler "packs" fields. I measure memory usage of classes. I break down all the allocations.
Info: In class "A", the byte and int fields are not grouped by their type. But in class "B", the bytes and ints are grouped by type.
Main: The Main method allocates 100,000 instances of both classes. The array memory usage is measured.
C# program that tests class field ordering
using System;
class A
{
byte b1;
int i1;
byte b2;
int i2;
byte b3;
int i3;
byte b4;
int i4;
}
class B
{
byte b1;
byte b2;
byte b3;
byte b4;
int i1;
int i2;
int i3;
int i4;
}
class Program
{
static void Main()
{
// ... Measure class "A".
long m1 = GC.GetTotalMemory(true);
A[] ar1 = new A[100000];
for (int i = 0; i < ar1.Length; i++)
{
ar1[i] = new A();
}
long m2 = GC.GetTotalMemory(true);
Console.WriteLine(m2 - m1);
Console.WriteLine((m2 - m1) / 100000);
ar1[0] = null;
ar1 = null;
// ... Measure class "B".
long m3 = GC.GetTotalMemory(true);
B[] ar2 = new B[100000];
for (int i = 0; i < ar2.Length; i++)
{
ar2[i] = new B();
}
long m4 = GC.GetTotalMemory(true);
Console.WriteLine(m4 - m3);
Console.WriteLine((m4 - m3) / 100000);
ar2[0] = null;
ar2 = null;
}
}
Output
3200016 [bytes total, A]
32 [bytes per element, A]
3200016 [bytes total, B]
32 [bytes per element, B]
Objects: The class reference (within the arrays) accounted for 4 bytes per object. An empty class (with no fields) required 12 bytes.
However: A class with just one int field also required 12 bytes. This is the smallest class size possible.
Info: I included the 4 bytes from the first int into the minimum class size. Then I added all the remaining fields.
And: The four byte fields occupied only four bytes. They were effectively packed together in memory.
Memory usage:
Class reference: 4 bytes
Class, empty: 12 bytes
Class with 1 int: 12 bytes
Int: 4 bytes
4 bytes
4 bytes
4 bytes
Byte: 1 byte
1 byte
1 byte
1 byte
Total: 4 bytes (reference)
12 bytes (class with 1 int)
12 bytes (3 remaining ints)
4 bytes (fields)
= 32 bytes
Indexer: An indexer is a type of property. It is used with simple syntax—the same syntax used for array accesses.
Indexer