Share via


Eigenschappen (F#)

Eigenschappen zijn leden die waarden vertegenwoordigen die zijn gekoppeld aan een object.

Syntaxis

// Property that has both get and set defined.
[ attributes ]
[ static ] member [accessibility-modifier] [self-identifier.]PropertyName
with [accessibility-modifier] get() =
    get-function-body
and [accessibility-modifier] set parameter =
    set-function-body

// Alternative syntax for a property that has get and set.
[ attributes-for-get ]
[ static ] member [accessibility-modifier-for-get] [self-identifier.]PropertyName =
    get-function-body
[ attributes-for-set ]
[ static ] member [accessibility-modifier-for-set] [self-identifier.]PropertyName
with set parameter =
    set-function-body

// Property that has get only.
[ attributes ]
[ static ] member [accessibility-modifier] [self-identifier.]PropertyName =
    get-function-body

// Alternative syntax for property that has get only.
[ attributes ]
[ static ] member [accessibility-modifier] [self-identifier.]PropertyName
with get() =
    get-function-body

// Property that has set only.
[ attributes ]
[ static ] member [accessibility-modifier] [self-identifier.]PropertyName
with set parameter =
    set-function-body

// Automatically implemented properties.
[ attributes ]
[ static ] member val [accessibility-modifier] PropertyName = initialization-expression [ with get, set ]

Opmerkingen

Eigenschappen vertegenwoordigen de relatie 'has a' in objectgeoriënteerde programmering, die gegevens vertegenwoordigt die zijn gekoppeld aan objectexemplaren of, voor statische eigenschappen, met het type.

U kunt eigenschappen op twee manieren declareren, afhankelijk van of u expliciet de onderliggende waarde (ook wel het backing-archief genoemd) voor de eigenschap wilt opgeven, of als u wilt toestaan dat de compiler automatisch de back-upopslag voor u genereert. Over het algemeen moet u de meer expliciete manier gebruiken als de eigenschap een niet-triviale implementatie heeft en de automatische manier waarop de eigenschap slechts een eenvoudige wrapper is voor een waarde of variabele. Als u een eigenschap expliciet wilt declareren, gebruikt u het member trefwoord. Deze declaratieve syntaxis wordt gevolgd door de syntaxis waarmee de get en set methoden, ook benoemde accessors, worden opgegeven. De verschillende vormen van de expliciete syntaxis die in de syntaxissectie worden weergegeven, worden gebruikt voor eigenschappen lezen/schrijven, alleen-lezen en alleen-schrijven. Voor eigenschappen met het kenmerk Alleen-lezen definieert u alleen een get methode. Voor alleen-schrijven-eigenschappen definieert u alleen een set methode. Wanneer een eigenschap zowel getset als accessors heeft, kunt u met de alternatieve syntaxis kenmerken en toegankelijkheidsaanpassingen opgeven die voor elke toegangsfunctie verschillen, zoals wordt weergegeven in de volgende code.

// A read-only property.
member this.MyReadOnlyProperty = myInternalValue
// A write-only property.
member this.MyWriteOnlyProperty with set (value) = myInternalValue <- value
// A read-write property.
member this.MyReadWriteProperty
    with get () = myInternalValue
    and set (value) = myInternalValue <- value

Voor lees-/schrijfeigenschappen, die zowel een als set een get methode hebben, kan de volgorde van get en set kunnen worden omgekeerd. U kunt ook de syntaxis opgeven die alleen wordt get weergegeven en de syntaxis die alleen wordt set weergegeven in plaats van de gecombineerde syntaxis te gebruiken. Als u dit doet, kunt u gemakkelijker opmerkingen maken over de persoon get of set methode, als dat iets is wat u mogelijk moet doen. Dit alternatief voor het gebruik van de gecombineerde syntaxis wordt weergegeven in de volgende code.

member this.MyReadWriteProperty with get () = myInternalValue
member this.MyReadWriteProperty with set (value) = myInternalValue <- value

Privéwaarden die de gegevens voor eigenschappen bevatten, worden back-uparchieven genoemd. Als u wilt dat de compiler het backing-archief automatisch maakt, gebruikt u de trefwoorden member val, laat u de self-id weg en geeft u vervolgens een expressie op om de eigenschap te initialiseren. Als de eigenschap onveranderbaar moet zijn, neemt u dit op with get, set. Het volgende klassetype bevat bijvoorbeeld twee automatisch geïmplementeerde eigenschappen. Property1 is alleen-lezen en wordt geïnitialiseerd voor het argument dat is opgegeven voor de primaire constructor en Property2 is een settabeleigenschap die is geïnitialiseerd op een lege tekenreeks:

type MyClass(property1 : int) =
member val Property1 = property1
member val Property2 = "" with get, set

Automatisch geïmplementeerde eigenschappen maken deel uit van de initialisatie van een type, dus ze moeten worden opgenomen vóór andere liddefinities, net als let bindingen en do bindingen in een typedefinitie. Houd er rekening mee dat de expressie die een automatisch geïmplementeerde eigenschap initialiseert, alleen wordt geëvalueerd bij de initialisatie en niet telkens wanneer de eigenschap wordt geopend. Dit gedrag is in tegenstelling tot het gedrag van een expliciet geïmplementeerde eigenschap. Wat dit effectief betekent, is dat de code voor het initialiseren van deze eigenschappen wordt toegevoegd aan de constructor van een klasse. Houd rekening met de volgende code die dit verschil laat zien:

type MyClass() =
    let random  = new System.Random()
    member val AutoProperty = random.Next() with get, set
    member this.ExplicitProperty = random.Next()

let class1 = new MyClass()

printfn $"class1.AutoProperty = %d{class1.AutoProperty}"
printfn $"class1.ExplicitProperty = %d{class1.ExplicitProperty}"

Uitvoer

class1.AutoProperty = 1853799794
class1.AutoProperty = 1853799794
class1.ExplicitProperty = 978922705
class1.ExplicitProperty = 1131210765

In de uitvoer van de voorgaande code ziet u dat de waarde van AutoProperty ongewijzigd blijft wanneer deze herhaaldelijk wordt aangeroepen, terwijl de ExplicitProperty telkens wordt gewijzigd wanneer deze wordt aangeroepen. Dit laat zien dat de expressie voor een automatisch geïmplementeerde eigenschap niet telkens wordt geëvalueerd, net zoals de gettermethode voor de expliciete eigenschap.

Waarschuwing

Er zijn enkele bibliotheken, zoals Entity Framework (System.Data.Entity) die aangepaste bewerkingen uitvoeren in basisklasseconstructors die niet goed werken met de initialisatie van automatisch geïmplementeerde eigenschappen. Probeer in die gevallen expliciete eigenschappen te gebruiken.

Eigenschappen kunnen lid zijn van klassen, structuren, gediscrimineerde samenvoegingen, records, interfaces en typeextensies en kunnen ook worden gedefinieerd in objectexpressies.

Kenmerken kunnen worden toegepast op eigenschappen. Als u een kenmerk wilt toepassen op een eigenschap, schrijft u het kenmerk op een afzonderlijke regel vóór de eigenschap. Zie Kenmerken voor meer informatie.

Eigenschappen zijn standaard openbaar. Toegankelijkheidsaanpassingen kunnen ook worden toegepast op eigenschappen. Als u een toegankelijkheidsaanpassing wilt toepassen, voegt u deze direct vóór de naam van de eigenschap toe als deze moet worden toegepast op zowel de get als set de methoden. Voeg deze toe vóór de get en set trefwoorden als voor elke toegangsfunctie verschillende toegankelijkheid is vereist. De toegankelijkheidsaanpassing kan een van de volgende zijn: public, private, internal. Zie Toegangsbeheer voor meer informatie.

Implementaties van eigenschappen worden telkens uitgevoerd wanneer een eigenschap wordt geopend.

Eigenschappen van statisch en exemplaar

Eigenschappen kunnen statische eigenschappen of exemplaareigenschappen zijn. Statische eigenschappen kunnen zonder exemplaar worden aangeroepen en worden gebruikt voor waarden die zijn gekoppeld aan het type, niet met afzonderlijke objecten. Voor statische eigenschappen laat u de self-id weg. De self-id is vereist voor exemplaareigenschappen.

De volgende definitie van statische eigenschap is gebaseerd op een scenario waarin u een statisch veld myStaticValue hebt dat het backingarchief voor de eigenschap is.

static member MyStaticProperty
    with get() = myStaticValue
    and set(value) = myStaticValue <- value

Eigenschappen kunnen ook matrixachtig zijn, in dat geval worden ze geïndexeerde eigenschappen genoemd. Zie Geïndexeerde eigenschappen voor meer informatie.

Aantekening voor eigenschappen typen

In veel gevallen heeft de compiler voldoende informatie om het type eigenschap af te stellen van het type backing-archief, maar u kunt het type expliciet instellen door een typeaantekening toe te voegen.

// To apply a type annotation to a property that does not have an explicit
// get or set, apply the type annotation directly to the property.
member this.MyProperty1 : int = myInternalValue
// If there is a get or set, apply the type annotation to the get or set method.
member this.MyProperty2 with get() : int = myInternalValue

Accessors voor eigenschappensets gebruiken

U kunt eigenschappen instellen die accessors bieden set met behulp van de <- operator.

// Assume that the constructor argument sets the initial value of the
// internal backing store.
let mutable myObject = new MyType(10)
myObject.MyProperty <- 20
printfn "%d" (myObject.MyProperty)

De uitvoer is 20.

Abstracte eigenschappen

Eigenschappen kunnen abstract zijn. Net als bij methoden betekent abstract alleen dat er een virtuele verzending is gekoppeld aan de eigenschap. Abstracte eigenschappen kunnen echt abstract zijn, dat wil gezegd, zonder definitie in dezelfde klasse. De klasse die een dergelijke eigenschap bevat, is daarom een abstracte klasse. Abstract kan ook alleen betekenen dat een eigenschap virtueel is, en in dat geval moet een definitie aanwezig zijn in dezelfde klasse. Houd er rekening mee dat abstracte eigenschappen niet privé mogen zijn en als de ene accessor abstract is, moet de andere ook abstract zijn. Zie Abstract-klassen voor meer informatie over abstracte klassen.

// Abstract property in abstract class.
// The property is an int type that has a get and
// set method
[<AbstractClass>]
type AbstractBase() =
    abstract Property1: int with get, set

// Implementation of the abstract property
type Derived1() =
    inherit AbstractBase()
    let mutable value = 10

    override this.Property1
        with get () = value
        and set (v: int) = value <- v

// A type with a "virtual" property.
type Base1() =
    let mutable value = 10
    abstract Property1: int with get, set

    default this.Property1
        with get () = value
        and set (v: int) = value <- v

// A derived type that overrides the virtual property
type Derived2() =
    inherit Base1()
    let mutable value2 = 11

    override this.Property1
        with get () = value2
        and set (v) = value2 <- v

Zie ook