Consider the physical computer you are using. It has many properties—a size, a weight, a date it was built. Properties describe this computer.
We use properties on a class
(like a Computer class
) to describe the class
. They can be set and read from like other fields, and special code can be run.
To start, we introduce an Example class
. One field, an integer, is present—it is used as a backing store for the Number property.
int
property in the Example class
. Number provides get and set implementations.class
.using System; class Example { int _number; public int Number { get { return this._number; } set { this._number = value; } } } class Program { static void Main() { Example example = new Example(); example.Number = 5; // set { } Console.WriteLine(example.Number); // get { } } }5
We see automatically implemented property syntax in C#. A hidden field is generated—then the get and set statements are expanded to use that hidden field.
using System;
class Example
{
public int Number
{
get;
set;
}
}
class Program
{
static void Main()
{
Example example = new Example();
example.Number = 8;
example.Number *= 4;
Console.WriteLine(example.Number);
}
}32
Enum
This example shows the DayOfWeek
enum
type in a property. We also insert code in the getter (or setter) that checks the backing store or the parameter value.
enum
types like DayOfWeek
. Many properties will use string
or int
.using System;
class Example
{
DayOfWeek _day;
public DayOfWeek Day
{
get
{
// We don't allow this to be used on Friday.
if (this._day == DayOfWeek.Friday)
{
throw new Exception("Invalid access");
}
return this._day;
}
set
{
this._day = value;
}
}
}
class Program
{
static void Main()
{
Example example = new Example();
example.Day = DayOfWeek.Monday;
Console.WriteLine(example.Day == DayOfWeek.Monday);
}
}True
We make a private property. Here the IsFound
property can only be set in the Example class
. We set it in the Example constructor.
Program.Main
method by using an Example instance.using System; class Example { public Example() { // Set the private property. this.IsFound = true; } bool _found; public bool IsFound { get { return this._found; } private set { // Can only be called in this class. this._found = value; } } } class Program { static void Main() { Example example = new Example(); Console.WriteLine(example.IsFound); } }True
We can also make an entire property private. If we do this, we can only use the property in the same enclosing class
.
class
.using System; class Example { int _id; private int Id { get { return this._id; } set { this._id = value; } } public void Display() { // Access the private property in this method. this.Id = 7; Console.WriteLine(this.Id); } } class Program { static void Main() { Example example = new Example(); example.Display(); } }7
Properties can also be static
—this means they are associated with the type and not an instance. Static classes can only have static
properties.
using System; class Example { static int _count; public static int Count { get { // Side effect of this property. _count++; return _count; } } } class Program { static void Main() { Console.WriteLine(Example.Count); Console.WriteLine(Example.Count); Console.WriteLine(Example.Count); } }1 2 3
Let us consider how to make getters or setters on an automatic property. We cannot omit either the getter or setter in this kind of property.
using System;
class Example
{
public Example()
{
// Use private setter in the constructor.
this.Id = new Random().Next();
}
public int Id
{
get;
private set;
}
}
class Program
{
static void Main()
{
Example example = new Example();
Console.WriteLine(example.Id);
}
}2077325073
Automatic properties have support for default values much like fields. Here we assign the Quantity property of Medication to 30 by default.
using System;
class Medication
{
public int Quantity { get; set; } = 30; // Has default value.
}
class Program
{
static void Main()
{
Medication med = new Medication();
// The quantity is by default 30.
Console.WriteLine(med.Quantity);
// We can change the quantity.
med.Quantity *= 2;
Console.WriteLine(med.Quantity);
}
}30
60
We can use lambda-style syntax to specify properties. These are expression-bodied properties—we use "get" and "set" and then the result on the right side.
class Program { private static int test; public static int Test { get => test; set => test = value; } static void Main() { // Use the property. Program.Test = 200; System.Console.WriteLine(Program.Test); } }200
Suppose we wish to have a property that is not changeable (mutable) after its creation. It can only be initialized, not set.
init
" keyword to specify that the class
Test here has an Info property that can be initialized, but not set afterwards.using System; class Test { public string Info { get; init; } } class Program { static void Main() { // Use the init setter with an initializer. var test = new Test() { Info = "Ok" }; // The Info is ok. Console.WriteLine(test.Info); } }Ok
Compiler optimizations ensure that properties are efficient. These same optimizations are used on methods, which share the underlying implementation with properties.
using System; using System.Diagnostics; class Program { static string _backing; // Backing store for property. static string Property // Getter and setter. { get { return _backing; } set { _backing = value; } } static string Field; // Static field. static void Main() { const int m = 100000000; for (int x = 0; x < 10; x++) // Ten tests. { Stopwatch s1 = new Stopwatch(); s1.Start(); // Version 1: test property. for (int i = 0; i < m; i++) { Property = "string"; if (Property == "cat") { } } s1.Stop(); Stopwatch s2 = new Stopwatch(); s2.Start(); // Version 2: test field. for (int i = 0; i < m; i++) { Field = "string"; if (Field == "cat") { } } s2.Stop(); Console.WriteLine("{0},{1}", s1.ElapsedMilliseconds, s2.ElapsedMilliseconds); } } }Property get/set: 604.6 ms Field read/assign: 603.6 ms
Properties are used throughout most C# programs. They are a powerful way to replace methods. They present a more intuitive way to use objects.