Anonim Kayıtlar

Anonim kayıtlar, kullanılmadan önce bildirilmesini gerektirmeyen adlandırılmış değerlerin basit toplamalarda bulunur. Bunları yapılar veya başvuru türleri olarak bildirebilirsiniz. Bunlar varsayılan olarak başvuru türlerdir.

Syntax

Aşağıdaki örneklerde anonim kayıt sözdizimi gösterilmektedir. İle ayrılmış öğeler [item] isteğe bağlıdır.

// Construct an anonymous record
let value-name = [struct] {| Label1: Type1; Label2: Type2; ...|}

// Use an anonymous record as a type parameter
let value-name = Type-Name<[struct] {| Label1: Type1; Label2: Type2; ...|}>

// Define a parameter with an anonymous record as input
let function-name (arg-name: [struct] {| Label1: Type1; Label2: Type2; ...|}) ...

Temel kullanım

Anonim kayıtlar, örnek oluşturma işleminden önce bildirilmesini gerektirmeyen F # kayıt türleri olarak en iyi şekilde düşünülebilir.

Örneğin, burada anonim bir kayıt üreten bir işlevle etkileşim kurabilirsiniz:

open System

let getCircleStats radius =
    let d = radius * 2.0
    let a = Math.PI * (radius ** 2.0)
    let c = 2.0 * Math.PI * radius

    {| Diameter = d; Area = a; Circumference = c |}

let r = 2.0
let stats = getCircleStats r
printfn "Circle with radius: %f has diameter %f, area %f, and circumference %f"
    r stats.Diameter stats.Area stats.Circumference

Aşağıdaki örnek, printCircleStats giriş olarak anonim bir kayıt alan bir işlevle önceki bir şekilde genişler:

open System

let getCircleStats radius =
    let d = radius * 2.0
    let a = Math.PI * (radius ** 2.0)
    let c = 2.0 * Math.PI * radius

    {| Diameter = d; Area = a; Circumference = c |}

let printCircleStats r (stats: {| Area: float; Circumference: float; Diameter: float |}) =
    printfn "Circle with radius: %f has diameter %f, area %f, and circumference %f"
        r stats.Diameter stats.Area stats.Circumference

let r = 2.0
let stats = getCircleStats r
printCircleStats r stats

printCircleStatsGiriş türü derlenemeyeceği için aynı "şekle" sahip olmayan herhangi bir anonim kayıt türü ile çağırma başarısız olur:

printCircleStats r {| Diameter = 2.0; Area = 4.0; MyCircumference = 12.566371 |}
// Two anonymous record types have mismatched sets of field names
// '["Area"; "Circumference"; "Diameter"]' and '["Area"; "Diameter"; "MyCircumference"]'

Yapı anonim kayıtları

Anonim kayıtlar, isteğe bağlı anahtar sözcüğüyle yapı olarak da tanımlanabilir struct . Aşağıdaki örnek, bir struct anonim kaydı üreterek ve tüketerek bir öncekini genişlettiğini azaltır:

open System

let getCircleStats radius =
    let d = radius * 2.0
    let a = Math.PI * (radius ** 2.0)
    let c = 2.0 * Math.PI * radius

    // Note that the keyword comes before the '{| |}' brace pair
    struct {| Area = a; Circumference = c; Diameter = d |}

// the 'struct' keyword also comes before the '{| |}' brace pair when declaring the parameter type
let printCircleStats r (stats: struct {| Area: float; Circumference: float; Diameter: float |}) =
    printfn "Circle with radius: %f has diameter %f, area %f, and circumference %f"
        r stats.Diameter stats.Area stats.Circumference

let r = 2.0
let stats = getCircleStats r
printCircleStats r stats

Struclük çıkarımı

Yapı anonim kayıtları struct , çağrı sitesinde anahtar sözcüğü belirtmeniz gerekmeyen "yapı zaman çıkarımı" için de izin verir. Bu örnekte, ' i struct çağırırken anahtar sözcüğünü yok edin printCircleStats :


let printCircleStats r (stats: struct {| Area: float; Circumference: float; Diameter: float |}) =
    printfn "Circle with radius: %f has diameter %f, area %f, and circumference %f"
        r stats.Diameter stats.Area stats.Circumference

printCircleStats r {| Area = 4.0; Circumference = 12.6; Diameter = 12.6 |}

Ters desenler- struct giriş türünün bir struct anonim kaydı olmadığında belirtme, derlenmeyecektir.

Anonim kayıtları diğer türler içine ekleme

Durumları kayıtları olan ayrılmış birleşimler bildirmek yararlı olur. Ancak Kayıtlardaki veriler ayrılmış birleşimle aynı türde ise, tüm türleri birbirini dışlayan özyinelemeli olarak tanımlamanız gerekir. Anonim kayıtları kullanmak bu kısıtlamayı önler. Aşağıdaki örnek bir tür ve bir düzenin onunla eşleşen işlevdir:

type FullName = { FirstName: string; LastName: string }

// Note that using a named record for Manager and Executive would require mutually recursive definitions.
type Employee =
    | Engineer of FullName
    | Manager of {| Name: FullName; Reports: Employee list |}
    | Executive of {| Name: FullName; Reports: Employee list; Assistant: Employee |}

let getFirstName e =
    match e with
    | Engineer fullName -> fullName.FirstName
    | Manager m -> m.Name.FirstName
    | Executive ex -> ex.Name.FirstName

İfadeleri Kopyala ve Güncelleştir

Anonim kayıtlar kopyalama ve güncelleştirme ifadeleriile oluşturmayı destekler. Örneğin, var olan bir kaynağın verilerini kopyalayan bir anonim kaydın yeni bir örneğini nasıl oluşturabileceğiniz aşağıda açıklanmıştır:

let data = {| X = 1; Y = 2 |}
let data' = {| data with Y = 3 |}

Ancak, adlandırılmış kayıtlardan farklı olarak, anonim kayıtlar kopyalama ve güncelleştirme ifadelerine tamamen farklı formlar oluşturmanız için izin verir. Aşağıdaki örnek, önceki örnekteki aynı anonim kaydı alır ve yeni bir anonim kayda genişletir:

let data = {| X = 1; Y = 2 |}
let expandedData = {| data with Z = 3 |} // Gives {| X=1; Y=2; Z=3 |}

Adlandırılmış kayıt örneklerinden anonim kayıtlar oluşturmak da mümkündür:

type R = { X: int }
let data = { X = 1 }
let data' = {| data with Y = 2 |} // Gives {| X=1; Y=2 |}

Ayrıca, başvuruya ve yapı anonim kayıtlarına veri kopyalayabilirsiniz:

// Copy data from a reference record into a struct anonymous record
type R1 = { X: int }
let r1 = { X = 1 }

let data1 = struct {| r1 with Y = 1 |}

// Copy data from a struct record into a reference anonymous record
[<Struct>]
type R2 = { X: int }
let r2 = { X = 1 }

let data2 = {| r1 with Y = 1 |}

// Copy the reference anonymous record data into a struct anonymous record
let data3 = struct {| data2 with Z = r2.X |}

Anonim kayıtların özellikleri

Anonim kayıtlar, nasıl kullanılabilecekleri hakkında tam olarak anlamak için gereken birçok özelliğe sahiptir.

Anonim kayıtlar kabul edilir

Anonim kayıtlar nominal türlerdir. Bunlar, önde gelen bildirim gerektirmeyen adlandırılmış kayıt türleri (de kabul edilir) olarak en iyi şekilde düşünüldüler.

İki anonim kayıt bildirimi ile aşağıdaki örneği göz önünde bulundurun:

let x = {| X = 1 |}
let y = {| Y = 1 |}

xVe y değerleri farklı türlere sahiptir ve birbiriyle uyumlu değildir. Bunlar equatable değildir ve karşılaştırılabilir değildir. Bunu göstermek için adlandırılmış bir kayıt eşdeğerini göz önünde bulundurun:

type X = { X: int }
type Y = { Y: int }

let x = { X = 1 }
let y = { Y = 1 }

Tür Denkliği veya karşılaştırmayla ilgili olarak adlandırılmış kayıt eşdeğerleri ile karşılaştırıldığında anonim kayıtlar hakkında doğal olarak farklı bir şey yoktur.

Anonim kayıtlar yapısal eşitlik ve karşılaştırma kullanır

Kayıt türleri gibi anonim kayıtlar yapısal equatable ve karşılaştırılabilir. Bu yalnızca, tüm bileşen türleri eşitlik ve karşılaştırmayı destekliyorsa, örneğin, kayıt türleriyle geçerlidir. Eşitlik veya karşılaştırmayı desteklemek için, iki anonim kayıt aynı "şekle" sahip olmalıdır.

{| a = 1+1 |} = {| a = 2 |} // true
{| a = 1+1 |} > {| a = 1 |} // true

// error FS0001: Two anonymous record types have mismatched sets of field names '["a"]' and '["a"; "b"]'
{| a = 1 + 1 |} = {| a = 2;  b = 1|}

Anonim kayıtlar seri hale getirilebilir

Anonim kayıtları, adlandırılmış kayıtlarla yaptığınız gibi seri hale getirebilirsiniz. Newtonsoft. JSONkullanarak bir örnek aşağıda verilmiştir:

open Newtonsoft.Json

let phillip' = {| name="Phillip"; age=28 |}
let philStr = JsonConvert.SerializeObject(phillip')

let phillip = JsonConvert.DeserializeObject<{|name: string; age: int|}>(philStr)
printfn $"Name: {phillip.name} Age: %d{phillip.age}"

Anonim kayıtlar, serileştirilmiş/seri durumdan çıkarılan türler için bir etki alanı tanımlamaya gerek olmadan bir ağ üzerinden hafif veri göndermek için yararlıdır.

C# anonim türleriyle birlikte çalışan anonim kayıtlar

C# anonim türlerininkullanılmasını gerektiren bir .NET API 'si kullanmak mümkündür. C# anonim türleri, anonim kayıtlar kullanılarak ile birlikte çalışmak için önemsiz bir tür. Aşağıdaki örnek, anonim kayıtların adsız bir tür gerektiren bir LINQ aşırı yüklemesini çağırmak için nasıl kullanılacağını gösterir:

open System.Linq

let names = [ "Ana"; "Felipe"; "Emilia"]
let nameGrouping = names.Select(fun n -> {| Name = n; FirstLetter = n[0] |})
for ng in nameGrouping do
    printfn $"{ng.Name} has first letter {ng.FirstLetter}"

.NET genelinde bir anonim türde geçirme kullanılması gereken çok sayıda diğer API 'Ler vardır. Anonim kayıtlar, bu kişilerle çalışmaya yönelik aracımız.

Sınırlamalar

Anonim kayıtlar, kullanımlarında bazı kısıtlamalar vardır. Bazıları tasarımına göre değişir, ancak başkaları değiştirebilecektir.

Model eşleştirme sınırlamaları

Anonim kayıtlar, adlandırılmış kayıtlardan farklı olarak, model eşleştirmeyi desteklemez. Üç neden vardır:

  1. Adlandırılmış kayıt türlerinden farklı olarak, bir düzenin adsız kaydın her alanı için bir hesaba sahip olması gerekir. Bunun nedeni, anonim kayıtların yapısal alt yazmayı desteklememe yöntemidir. Bunlar, nominal türlerdir.
  2. (1) nedeniyle, her farklı düzen farklı bir anonim kayıt türünü aşacağından, desen eşleştirme ifadesinde ek desenler olamaz.
  3. (2) nedeniyle, herhangi bir anonim kayıt deseninin "nokta" gösterimi kullanmaktan daha ayrıntılı olması gerekir.

Sınırlı bağlamlarda model eşleştirmeye izin verenaçık bir dil önerisi vardır.

Değiştirici ile sınırlamalar

Şu anda verilerle adsız bir kayıt tanımlamak mümkün değildir mutable . Değişebilir verilere izin veren açık bir dil önerisi vardır.

Struct anonim kayıtlarıyla sınırlamalar

Struct anonim kayıtlarını veya olarak bildirmek mümkün değildir IsByRefLike IsReadOnly . Ve anonim kayıtlar için açık bir dil önerisi vardır IsByRefLike IsReadOnly .