Movatterモバイル変換


[0]ホーム

URL:


Skip to main content

This browser is no longer supported.

Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

Download Microsoft EdgeMore info about Internet Explorer and Microsoft Edge
Table of contentsExit editor mode

Properties (C# Programming Guide)

Feedback

In this article

Aproperty is a member that provides a flexible mechanism to read, write, or compute the value of a data field. Properties appear as public data members, but they're implemented as special methods calledaccessors. This feature enables callers to access data easily and still helps promote data safety and flexibility. The syntax for properties is a natural extension to fields. A field defines a storage location:

public class Person{    public string? FirstName;    // Omitted for brevity.}

Automatically implemented properties

A property definition contains declarations for aget andset accessor that retrieves and assigns the value of that property:

public class Person{    public string? FirstName { get; set; }    // Omitted for brevity.}

The preceding example shows anautomatically implemented property. The compiler generates a hidden backing field for the property. The compiler also implements the body of theget andset accessors. Any attributes are applied to the automatically implemented property. You can apply the attribute to the compiler-generated backing field by specifying thefield: tag on the attribute.

You can initialize a property to a value other than the default by setting a value after the closing brace for the property. You might prefer the initial value for theFirstName property to be the empty string rather thannull. You would specify that as shown in the following code:

public class Person{    public string FirstName { get; set; } = string.Empty;    // Omitted for brevity.}

Field backed properties

In C# 14, you can add validation or other logic in the accessor for a property using thefield keyword. Thefield keyword accesses the compiler synthesized backing field for a property. It enables you to write a property accessor without explicitly declaring a separate backing field.

public class Person{    public string? FirstName     {         get;        set => field = value.Trim();     }    // Omitted for brevity.}

Required properties

The preceding example allows a caller to create aPerson using the default constructor, without setting theFirstName property. The property changed type to anullable string. You canrequire callers to set a property:

public class Person{    public Person() { }    [SetsRequiredMembers]    public Person(string firstName) => FirstName = firstName;    public required string FirstName { get; init; }    // Omitted for brevity.}

The preceding code makes two changes to thePerson class. First, theFirstName property declaration includes therequired modifier. That means any code that creates a newPerson must set this property using anobject initializer. Second, the constructor that takes afirstName parameter has theSystem.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute attribute. This attribute informs the compiler that this constructor setsallrequired members. Callers using this constructor aren't required to setrequired properties with an object initializer.

Important

Don't confuserequired withnon-nullable. It's valid to set arequired property tonull ordefault. If the type is non-nullable, such asstring in these examples, the compiler issues a warning.

var aPerson = new Person("John");aPerson = new Person { FirstName = "John"};// Error CS9035: Required member `Person.FirstName` must be set://aPerson2 = new Person();

Expression body definitions

Property accessors often consist of single-line statements. The accessors assign or return the result of an expression. You can implement these properties as expression-bodied members. Expression body definitions consist of the=> token followed by the expression to assign to or retrieve from the property.

Read-only properties can implement theget accessor as an expression-bodied member. The following example implements the read-onlyName property as an expression-bodied member:

public class Person{    public Person() { }    [SetsRequiredMembers]    public Person(string firstName, string lastName)    {        FirstName = firstName;        LastName = lastName;    }    public required string FirstName { get; init; }    public required string LastName { get; init; }    public string Name => $"{FirstName} {LastName}";    // Omitted for brevity.}

TheName property is a computed property. There's no backing field forName. The property computes it each time.

Access control

The preceding examples showed read / write properties. You can also create read-only properties, or give different accessibility to the set and get accessors. Suppose that yourPerson class should only enable changing the value of theFirstName property from other methods in the class. You could give the set accessorprivate accessibility instead ofinternal orpublic:

public class Person{    public string? FirstName { get; private set; }    // Omitted for brevity.}

TheFirstName property can be read from any code, but it can be assigned only from code in thePerson class.

You can add any restrictive access modifier to either the set or get accessors. An access modifier on an individual accessor must be more restrictive than the access of the property. The preceding code is legal because theFirstName property ispublic, but the set accessor isprivate. You couldn't declare aprivate property with apublic accessor. Property declarations can also be declaredprotected,internal,protected internal, or, evenprivate.

There are two special access modifiers forset accessors:

  • Aset accessor can haveinit as its access modifier. Thatset accessor can be called only from an object initializer or the type's constructors. It's more restrictive thanprivate on theset accessor.
  • An automatically implemented property can declare aget accessor without aset accessor. In that case, the compiler allows theset accessor to be called only from the type's constructors. It's more restrictive than theinit accessor on theset accessor.

Modify thePerson class so as follows:

public class Person{    public Person(string firstName) => FirstName = firstName;    public string FirstName { get; }    // Omitted for brevity.}

The preceding example requires callers to use the constructor that includes theFirstName parameter. Callers can't useobject initializers to assign a value to the property. To support initializers, you can make theset accessor aninit accessor, as shown in the following code:

public class Person{    public Person() { }    public Person(string firstName) => FirstName = firstName;    public string? FirstName { get; init; }    // Omitted for brevity.}

These modifiers are often used with therequired modifier to force proper initialization.

Properties with backing fields

You can mix the concept of a computed property with a private field and create acached evaluated property. For example, update theFullName property so that the string formatting happens on the first access:

public class Person{    public Person() { }    [SetsRequiredMembers]    public Person(string firstName, string lastName)    {        FirstName = firstName;        LastName = lastName;    }    public required string FirstName { get; init; }    public required string LastName { get; init; }    private string? _fullName;    public string FullName    {        get        {            if (_fullName is null)                _fullName = $"{FirstName} {LastName}";            return _fullName;        }    }}

This implementation works because theFirstName andLastName properties are readonly. People can change their name. Updating theFirstName andLastName properties to allowset accessors requires you to invalidate any cached value forfullName. You modify theset accessors of theFirstName andLastName property so thefullName field is calculated again:

public class Person{    private string? _firstName;    public string? FirstName    {        get => _firstName;        set        {            _firstName = value;            _fullName = null;        }    }    private string? _lastName;    public string? LastName    {        get => _lastName;        set        {            _lastName = value;            _fullName = null;        }    }    private string? _fullName;    public string FullName    {        get        {            if (_fullName is null)                _fullName = $"{FirstName} {LastName}";            return _fullName;        }    }}

This final version evaluates theFullName property only when needed. The previously calculated version is used if valid. Otherwise, the calculation updates the cached value. Developers using this class don't need to know the details of the implementation. None of these internal changes affect the use of the Person object.

Beginning with C# 13, you can createpartial properties inpartial classes. The implementing declaration for apartial property can't be an automatically implemented property. An automatically implemented property uses the same syntax as a declaring partial property declaration.

Properties

Properties are a form of smart fields in a class or object. From outside the object, they appear like fields in the object. However, properties can be implemented using the full palette of C# functionality. You can provide validation, different accessibility, lazy evaluation, or any requirements your scenarios need.

  • Simple properties that require no custom accessor code can be implemented either as expression body definitions or asautomatically implemented properties.
  • Properties enable a class to expose a public way of getting and setting values, while hiding implementation or verification code.
  • Aget property accessor is used to return the property value, and aset property accessor is used to assign a new value. Aninit property accessor is used to assign a new value only during object construction. These accessors can have different access levels. For more information, seeRestricting Accessor Accessibility.
  • Thevalue keyword is used to define the value theset orinit accessor is assigning.
  • Properties can beread-write (they have both aget and aset accessor),read-only (they have aget accessor but noset accessor), orwrite-only (they have aset accessor, but noget accessor). Write-only properties are rare.

C# Language Specification

For more information, seeProperties in theC# Language Specification. The language specification is the definitive source for C# syntax and usage.

See also

Collaborate with us on GitHub
The source for this content can be found on GitHub, where you can also create and review issues and pull requests. For more information, seeour contributor guide.

Feedback

Was this page helpful?

YesNoNo

Need help with this topic?

Want to try using Ask Learn to clarify or guide you through this topic?

Suggest a fix?

  • Last updated on

In this article

Was this page helpful?

YesNo
NoNeed help with this topic?

Want to try using Ask Learn to clarify or guide you through this topic?

Suggest a fix?