Egenskaper (F#)
Egenskaper är medlemmar som representerar värden som är associerade med ett objekt.
Syntax
// 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 ]
Kommentarer
Egenskaper representerar relationen "har en" i objektorienterad programmering, som representerar data som är associerade med objektinstanser eller, för statiska egenskaper, med typen .
Du kan deklarera egenskaper på två sätt, beroende på om du uttryckligen vill ange det underliggande värdet (kallas även backningsarkivet) för egenskapen, eller om du vill tillåta att kompilatorn automatiskt genererar lagringsplatsen åt dig. I allmänhet bör du använda det mer explicita sättet om egenskapen har en icke-trivial implementering och det automatiska sättet när egenskapen bara är en enkel omslutning för ett värde eller en variabel. Om du vill deklarera en egenskap explicit använder du nyckelordet member
. Den här deklarativa syntaxen följs av syntaxen get
som anger metoderna och set
, som även heter accessorer. De olika formerna av den explicita syntax som visas i syntaxavsnittet används för skriv-, skriv- och skrivskyddade egenskaper. För skrivskyddade egenskaper definierar du endast en get
metod. För skrivskyddade egenskaper definierar du endast en set
metod. Observera att när en egenskap har både get
och set
accessorer kan du med den alternativa syntaxen ange attribut och hjälpmedelsmodifierare som skiljer sig åt för varje accessor, vilket visas i följande kod.
// 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
För läs-/skrivegenskaper, som har både en get
och set
-metod, kan ordningen på get
och set
ångras. Du kan också ange den syntax som visas endast för get
och den syntax som visas endast för i stället för set
att använda den kombinerade syntaxen. Om du gör det blir det lättare att kommentera ut individen get
eller set
metoden, om det är något du kan behöva göra. Det här alternativet till att använda den kombinerade syntaxen visas i följande kod.
member this.MyReadWriteProperty with get () = myInternalValue
member this.MyReadWriteProperty with set (value) = myInternalValue <- value
Privata värden som innehåller data för egenskaper kallas för backningslager. Om du vill att kompilatorn ska skapa lagringsplatsen automatiskt använder du nyckelorden member val
, utelämnar självidentifieraren och anger sedan ett uttryck för att initiera egenskapen. Om egenskapen ska vara föränderlig inkluderar du with get, set
. Följande klasstyp innehåller till exempel två automatiskt implementerade egenskaper. Property1
är skrivskyddad och initieras till argumentet som tillhandahålls till den primära konstruktorn och Property2
är en initieringsbar egenskap som initieras till en tom sträng:
type MyClass(property1 : int) =
member val Property1 = property1
member val Property2 = "" with get, set
Automatiskt implementerade egenskaper är en del av initieringen av en typ, så de måste inkluderas före andra medlemsdefinitioner, precis som let
bindningar och do
bindningar i en typdefinition. Observera att uttrycket som initierar en automatiskt implementerad egenskap endast utvärderas vid initiering och inte varje gång egenskapen används. Det här beteendet står i kontrast till beteendet för en explicit implementerad egenskap. Det innebär i praktiken att koden för att initiera dessa egenskaper läggs till i konstruktorn för en klass. Tänk på följande kod som visar den här skillnaden:
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}"
Output
class1.AutoProperty = 1853799794
class1.AutoProperty = 1853799794
class1.ExplicitProperty = 978922705
class1.ExplicitProperty = 1131210765
Utdata från föregående kod visar att värdet för AutoProperty är oförändrat när det anropas upprepade gånger, medan ExplicitProperty ändras varje gång det anropas. Detta visar att uttrycket för en automatiskt implementerad egenskap inte utvärderas varje gång, liksom metoden getter för den explicita egenskapen.
Varning
Det finns vissa bibliotek, till exempel Entity Framework (System.Data.Entity
) som utför anpassade åtgärder i basklasskonstruktorer som inte fungerar bra med initieringen av automatiskt implementerade egenskaper. I dessa fall kan du prova att använda explicita egenskaper.
Egenskaper kan vara medlemmar i klasser, strukturer, diskriminerade fackföreningar, poster, gränssnitt och typtillägg och kan också definieras i objektuttryck.
Attribut kan tillämpas på egenskaper. Om du vill tillämpa ett attribut på en egenskap skriver du attributet på en separat rad före egenskapen. Mer information finns i Attribut.
Som standard är egenskaperna offentliga. Hjälpmedelsmodifierare kan också tillämpas på egenskaper. Om du vill använda en hjälpmedelsmodifierare lägger du till den omedelbart före namnet på egenskapen om den är avsedd att gälla för både get
metoderna och set
. Lägg till den före nyckelorden get
och set
om olika hjälpmedel krävs för varje åtkomst. Hjälpmedelsmodifierarenkan vara något av följande: public
, private
, internal
. Mer information finns i Åtkomstkontroll.
Egenskapsimplementeringar körs varje gång en egenskap används.
Egenskaper för statiska instanser och instanser
Egenskaper kan vara statiska egenskaper eller instansegenskaper. Statiska egenskaper kan anropas utan en instans och används för värden som är associerade med typen, inte med enskilda objekt. För statiska egenskaper utelämnar du självidentifieraren. Självidentifieraren krävs för instansegenskaper.
Följande statiska egenskapsdefinition baseras på ett scenario där du har ett statiskt fält myStaticValue
som är lagringsplatsen för egenskapen.
static member MyStaticProperty
with get() = myStaticValue
and set(value) = myStaticValue <- value
Egenskaper kan också vara matrisliknande, i vilket fall de kallas indexerade egenskaper. Mer information finns i Indexerade egenskaper.
Skriv kommentar för egenskaper
I många fall har kompilatorn tillräckligt med information för att härleda typen av en egenskap från typen av lagringsplats, men du kan ange typen explicit genom att lägga till en typanteckning.
// 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
Använda egenskapsuppsättningsåtkomster
Du kan ange egenskaper som ger set
åtkomst med hjälp av operatorn <-
.
// 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)
Utdata är 20.
Abstrakta egenskaper
Egenskaper kan vara abstrakta. Precis som med metoder abstract
betyder det bara att det finns en virtuell sändning som är associerad med egenskapen. Abstrakta egenskaper kan vara verkligt abstrakta, dvs. utan en definition i samma klass. Klassen som innehåller en sådan egenskap är därför en abstrakt klass. Alternativt kan abstrakt bara innebära att en egenskap är virtuell, och i så fall måste en definition finnas i samma klass. Observera att abstrakta egenskaper inte får vara privata, och om en accessor är abstrakt måste den andra också vara abstrakt. Mer information om abstrakta klasser finns i Abstrakta klasser.
// 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