An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
Nice question you've asked. First of all, let me clear something up for you: classes that you mentioned are never on the stack; they are always on the heap. When you "instantiate" an object with a certain type, or in simpler terms, when you create an object like that "Employee EmployeeInstance = new Employee();", it will always be created on the heap; structs if initiated or instantiated in a local variable, on the other hands, are created on the stack. This is how .NET/C# does it.
Now we got that out of the way, let's address your actual question regarding where these properties are stored on .NET:
See when you don't define custom getter and setter methods for your property like that
public class Employee
{
public int EmployeeID
{
get
{
return myfield;
// stuff
}
set
{
myfield = value;
// stuff
}
}
}
the C# compiler will create a field for your property and emit code to read and assign that field in those set and get methods; that is basically the compiler's way to do the extra work of creating that "myfield" for you. The created field is just like the other fields in your class: the compiler names it like that "<YourPropertyName>k__BackingField" and adds it to your class layout. Take a look as this code below:
...
public int EmployeeID
{
[CompilerGenerated]
get
{
return this.<EmployeeID>k__BackingField;
}
[CompilerGenerated]
set
{
this.<EmployeeID>k__BackingField = value;
}
}
public Employee()
{
}
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int <EmployeeID>k__BackingField;
}
This is how the compiler treats a property you define like that "EmployeeID{get; set;}" :)
The getter and the setter in the properties are just regular methods on the low level which the compiler names them like that "get_EmployeeID"; "set_EmployeeID":
Usually, the calls you make to these properties will be "inlined", and ultimately, your code will narrow down to a simple field assignment or memory read.
Hope that answers your question and others' :)