Kayıtlar (F#)
Kayıtlar, isteğe bağlı olarak üyelerle birlikte adlandırılmış değerlerin basit toplamlarını temsil eder. Bunlar yapı veya başvuru türleri olabilir. Bunlar varsayılan olarak başvuru türleridir.
Syntax
[ attributes ]
type [accessibility-modifier] typename =
{ [ mutable ] label1 : type1;
[ mutable ] label2 : type2;
... }
[ member-list ]
Açıklamalar
Önceki söz dizimsinde typename, kayıt türünün adıdır, label1 ve label2 ise etiket olarak adlandırılan değer adlarıdır ve type1 ve type2 bu değerlerin türleridir. member-list, tür için isteğe bağlı üye listesidir. başvuru türü [<Struct>] olan bir kayıt yerine yapı kaydı oluşturmak için özniteliğini kullanabilirsiniz.
Bazı örnekler aşağıda verilmiştir.
// Labels are separated by semicolons when defined on the same line.
type Point = { X: float; Y: float; Z: float; }
// You can define labels on their own line with or without a semicolon.
type Customer =
{ First: string
Last: string;
SSN: uint32
AccountNumber: uint32; }
// A struct record.
[<Struct>]
type StructPoint =
{ X: float
Y: float
Z: float }
Her etiket ayrı bir satırda olduğunda noktalı virgül isteğe bağlıdır.
Kayıt ifadeleri olarak bilinen ifadelerde değerleri ayarlayın. Derleyici, türü kullanılan etiketlerden çıkartır (etiketler diğer kayıt türlerinden yeterince ayrı ise). Küme ayraçları ({ }) kayıt ifadesinin içine alın. Aşağıdaki kod, ve etiketlerine sahip üç float öğeye sahip bir kaydı başlatan bir kayıt x ifadesi y z gösterir.
let mypoint = { X = 1.0; Y = 1.0; Z = -1.0; }
Aynı etiketlere sahip başka bir tür de varsa kısaltılmış formu kullanmayın.
type Point = { X: float; Y: float; Z: float; }
type Point3D = { X: float; Y: float; Z: float }
// Ambiguity: Point or Point3D?
let mypoint3D = { X = 1.0; Y = 1.0; Z = 0.0; }
En son bildirilen türün etiketleri, daha önce bildirilen türe göre önceliklidir, bu nedenle önceki örnekte mypoint3D olduğu kabul Point3D edildi. Aşağıdaki kodda olduğu gibi kayıt türünü açıkça belirtebilirsiniz.
let myPoint1 = { Point.X = 1.0; Y = 1.0; Z = 0.0; }
Yöntemler, tıpkı sınıf türlerinde olduğu gibi kayıt türleri için tanımlanabilir.
Kayıt İfadeleri Kullanarak Kayıt Oluşturma
Kayıtta tanımlanan etiketleri kullanarak kayıtları başlatabilirsiniz. Bunu yapmak için bir ifade kayıt ifadesi olarak adlandırılır. Kayıt ifadesini içine almak için ayraçları kullanın ve noktalı virgülleri sınırlayıcı olarak kullanın.
Aşağıdaki örnekte bir kaydın nasıl oluşturularak ilgili bilgiler ve bilgiler yer alelade bir şekilde liste
type MyRecord =
{ X: int
Y: int
Z: int }
let myRecord1 = { X = 1; Y = 2; Z = 3; }
Alanların tek satırda olup olmadığı ne olursa olsun, kayıt ifadesinde ve tür tanımında son alandan sonra gelen noktalı virgüller isteğe bağlıdır.
Bir kayıt oluşturdukta her alan için değer oluşturmanız gerekir. Başlatma ifadesinde herhangi bir alan için diğer alanların değerlerine başvuramazsınız.
Aşağıdaki kodda, türü myRecord2 alanların adlarından türe sahiptir. İsteğe bağlı olarak, tür adını açıkça belirtesiniz.
let myRecord2 = { MyRecord.X = 1; MyRecord.Y = 2; MyRecord.Z = 3 }
Başka bir kayıt oluşturma biçimi, mevcut bir kaydı kopyalamanız ve alan değerlerden bazılarının değişmesi gereken durumlarda yararlı olabilir. Aşağıdaki kod satırı bunu göstermektedir.
let myRecord3 = { myRecord2 with Y = 100; Z = 2 }
Kayıt ifadesinin bu biçimi, kayıt ifadesini kopyalama ve güncelleştirme olarak adlandırılan bir biçimdir.
Kayıtlar varsayılan olarak sabittir; ancak, bir kopyalama ve güncelleştirme ifadesi kullanarak değiştirilmiş kayıtları kolayca oluşturabilirsiniz. Ayrıca, table alanını açıkça belirtebilirsiniz.
type Car =
{ Make : string
Model : string
mutable Odometer : int }
let myCar = { Make = "Fabrikam"; Model = "Coupe"; Odometer = 108112 }
myCar.Odometer <- myCar.Odometer + 21
DefaultValue özniteliğini kayıt alanlarıyla birlikte kullanma. Varsayılan değerlerle başlatılan alanlarla kayıtların varsayılan örneklerini tanımlamak ve ardından varsayılan değerlerden farklı alanları ayarlamak için bir kopyalama ve kayıt ifadesini güncelleştirme kullanmak daha iyi bir yaklaşımdır.
// Rather than use [<DefaultValue>], define a default record.
type MyRecord =
{ Field1 : int
Field2 : int }
let defaultRecord1 = { Field1 = 0; Field2 = 0 }
let defaultRecord2 = { Field1 = 1; Field2 = 25 }
// Use the with keyword to populate only a few chosen fields
// and leave the rest with default values.
let rr3 = { defaultRecord1 with Field2 = 42 }
Karşılıklı Olarak Recursive Kayıtları Oluşturma
Bir kayıt oluştururken, daha sonra tanımlamak istediğiniz başka bir türe bağımlı olmak istiyor olabilir. Karşılıklı olarak tekrarlayıcı olacak kayıt türlerini tanımlamadıkça bu bir derleme hatasıdır.
Karşılıklı olarak tekrarlayan kayıtların tanımlanması anahtar sözcüğüyle and yapılır. Bu, 2 veya daha fazla kayıt türü arasında bağlantı sağlar.
Örneğin, aşağıdaki kod ve türünü Person Address karşılıklı olarak tekrarlayıcı olarak tanımlar:
// Create a Person type and use the Address type that is not defined
type Person =
{ Name: string
Age: int
Address: Address }
// Define the Address type which is used in the Person record
and Address =
{ Line1: string
Line2: string
PostCode: string
Occupant: Person }
Önceki örneği anahtar sözcüğü olmadan and tanımladıysanız derlemez. Karşılıklı and olarak tekrarlayan tanımlar için anahtar sözcüğü gereklidir.
Kayıtlarla Desen Eşleştirme
Kayıtlar desen eşleştirme ile kullanılabilir. Bazı alanları açıkça belirtebilirsiniz ve bir eşleşme oluştuğunda atanacak diğer alanlar için değişkenler sebilirsiniz. Aşağıdaki kod örneği bunu gösterir.
type Point3D = { X: float; Y: float; Z: float }
let evaluatePoint (point: Point3D) =
match point with
| { X = 0.0; Y = 0.0; Z = 0.0 } -> printfn "Point is at the origin."
| { X = xVal; Y = 0.0; Z = 0.0 } -> printfn "Point is on the x-axis. Value is %f." xVal
| { X = 0.0; Y = yVal; Z = 0.0 } -> printfn "Point is on the y-axis. Value is %f." yVal
| { X = 0.0; Y = 0.0; Z = zVal } -> printfn "Point is on the z-axis. Value is %f." zVal
| { X = xVal; Y = yVal; Z = zVal } -> printfn "Point is at (%f, %f, %f)." xVal yVal zVal
evaluatePoint { X = 0.0; Y = 0.0; Z = 0.0 }
evaluatePoint { X = 100.0; Y = 0.0; Z = 0.0 }
evaluatePoint { X = 10.0; Y = 0.0; Z = -1.0 }
Bu kodun çıkışı aşağıdaki gibidir.
Point is at the origin.
Point is on the x-axis. Value is 100.000000.
Point is at (10.000000, 0.000000, -1.000000).
Kayıtlar ve üyeler
Sınıflarda olduğu gibi kayıtlarda da üyeleri belirtabilirsiniz. Alanlar için destek yoktur. Kolay kayıt yapısı için statik üye Default tanımlamak yaygın bir yaklaşımdır:
type Person =
{ Name: string
Age: int
Address: string }
static member Default =
{ Name = "Phillip"
Age = 12
Address = "123 happy fun street" }
let defaultPerson = Person.Default
Bir kendi kendine tanımlayıcı kullanırsanız, bu tanımlayıcı üyesi çağrılır kaydın örneğine başvurur:
type Person =
{ Name: string
Age: int
Address: string }
member this.WeirdToString() =
this.Name + this.Address + string this.Age
let p = { Name = "a"; Age = 12; Address = "abc123" }
let weirdString = p.WeirdToString()
Kayıtlar ve Sınıflar Arasındaki Farklar
Kayıt alanları, içinde bulunan sınıf alanlarından özellik olarak otomatik olarak ortaya çıkarılmalarından farklıdır ve kayıt oluşturma ve kopyalamada kullanılırlar. Kayıt yapısı, sınıf yapısından da farklıdır. Kayıt türünde bir oluşturucu tanımamazsiniz. Bunun yerine, bu konuda açıklanan yapı söz dizimi geçerlidir. Sınıfların oluşturucu parametreleri, alanları ve özellikleri arasında doğrudan bir ilişkisi yoktur.
Birliktelik ve yapı türleri gibi kayıtlar da yapısal eşitlik semantiğine sahiptir. Sınıfların başvuru eşitliği semantiği vardır. Aşağıdaki kod örneği bunu gösteriyor.
type RecordTest = { X: int; Y: int }
let record1 = { X = 1; Y = 2 }
let record2 = { X = 1; Y = 2 }
if (record1 = record2) then
printfn "The records are equal."
else
printfn "The records are unequal."
Bu kodun çıkışı aşağıdaki gibidir:
The records are equal.
Sınıflarla aynı kodu yazarsanız, iki sınıf nesnesi yığındaki iki nesneyi temsil edecek ve yalnızca adresleri karşılaştıracak (sınıf türü yöntemi geçersiz kılmadıkça) iki sınıf nesnesi eşit System.Object.Equals olmayacaktır.
Kayıtlar için başvuru eşitliği gerekirse, kaydın üzerine [<ReferenceEquality>] özniteliğini ekleyin.