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.

Ayrıca bkz.