Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A névtelen rekordok a névvel ellátott értékek egyszerű összesítései, amelyeket nem kell deklarálni használat előtt. Deklarálhatja őket szerkezetként vagy referenciatípusként. Alapértelmezés szerint referenciatípusok.
Szemantika
Az alábbi példák a névtelen rekord szintaxisát mutatják be. Az [item] jelöléssel határolt elemek választhatóak.
// 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; ...|}) ...
Alapszintű használat
A névtelen rekordokat érdemes F# típusú rekordtípusoknak tekinteni, amelyeket nem kell deklarálni a példányosítás előtt.
Például az alábbi módon kezelheti egy névtelen rekordot előállító függvényt:
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
Az alábbi példa az előzőre bont ki egy printCircleStats függvényt, amely egy névtelen rekordot vesz fel bemenetként:
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
Az olyan névtelen rekordtípussal való hívás printCircleStats , amely nem ugyanazzal az "alakzattal" rendelkezik, mint a bemeneti típus, nem lesz lefordítva:
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"]'
Névtelen rekordok strukturálás
A névtelen rekordok strukturáltként is definiálhatók az opcionális struct kulcsszóval. Az alábbi példa egy strukturált névtelen rekord előállításával és felhasználásával bővíti az előzőt:
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
Strukturáltság következtetése
A névtelen rekordok strukturálása "strukturitási következtetést" is lehetővé tesz, ahol nem kell megadnia a kulcsszót struct a hívási helyen. Ebben a példában kihagyja a struct kulcsszót, amikor a printCircleStats hívást elvégzi.
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 |}
A fordított minta – ha struct van megadva, amikor a bemeneti típus nem strukturált névtelen rekord – nem fog lefordulni.
Névtelen rekordok beágyazása más típusokba
Érdemes deklarálni azokat a hátrányos megkülönböztetést alkalmazó szakszervezeteket , amelyeknek az ügyei rekordnak számítanak. Ha azonban a rekordok adatai megegyeznek a diszkriminált egyesítés típusával, minden típust kölcsönösen rekurzívként kell definiálnia. A névtelen rekordok használata elkerüli ezt a korlátozást. Az alábbiakban egy példatípust és függvényt mutatunk be, amely egyezik a mintával:
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
Kifejezések másolása és frissítése
A névtelen rekordok másolási és frissítési kifejezésekkel támogatják a konstrukciót. Például az alábbi módon hozhat létre egy névtelen rekord új példányát, amely egy meglévő adatát másolja:
let data = {| X = 1; Y = 2 |}
let data' = {| data with Y = 3 |}
A névvel ellátott rekordoktól eltérően azonban a névtelen rekordok lehetővé teszik, hogy teljesen új és különböző alakzatokat hozzon létre másolási és frissítési kifejezésekkel. A következő példa ugyanazt a névtelen rekordot veszi fel az előző példából, és egy új névtelen rekordra bontja:
let data = {| X = 1; Y = 2 |}
let expandedData = {| data with Z = 3 |} // Gives {| X=1; Y=2; Z=3 |}
Névtelen rekordokat is létre lehet hozni nevesített rekordok példányaiból:
type R = { X: int }
let data = { X = 1 }
let data' = {| data with Y = 2 |} // Gives {| X=1; Y=2 |}
Az adatokat átmásolhatja a hivatkozásból és a hivatkozásból, és strukturálhatja a névtelen rekordokat:
// 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 |}
Névtelen rekordok tulajdonságai
A névtelen rekordok számos olyan jellemzővel rendelkeznek, amelyek elengedhetetlenek a használatuk teljes megértéséhez.
A névtelen rekordok strukturális egyenlőséget és összehasonlítást használnak
A rekordtípusokhoz hasonlóan a névtelen rekordok is szerkezetileg egyenértékűek és összehasonlíthatók. Ez csak akkor igaz, ha minden összetevőtípus támogatja az egyenlőséget és az összehasonlítást, például a rekordtípusok esetében. Az egyenlőség vagy összehasonlítás támogatásához két névtelen rekordnak azonos "alakzattal" kell rendelkeznie.
{| 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|}
A névtelen rekordok szerializálhatók
A névtelen rekordokat ugyanúgy szerializálhatja, mint a nevesített rekordokat. Íme egy példa a Newtonsoft.Json használatával:
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}"
A névtelen rekordok akkor hasznosak, ha egyszerű adatokat küldenek egy hálózaton anélkül, hogy tartományt kellene definiálni a szerializált/deszerializált típusokhoz elöl.
A névtelen rekordok c# névtelen típusokkal működnek együtt
Olyan .NET API is használható, amely C# névtelen típusok használatát igényli. A C# névtelen típusok triviálisak a névtelen rekordok használatával való együttműködéshez. Az alábbi példa bemutatja, hogyan hívhat névtelen rekordokat egy névtelen típust igénylő LINQ-túlterhelés meghívásához:
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}"
A .NET-ben számos más API-t is használnak, amelyek névtelen típusú továbbítást igényelnek. A névtelen rekordok a velük végzett munka eszközei.
Korlátozások
A névtelen rekordok használata bizonyos korlátozásokkal rendelkezik. Némelyik a kialakításuk velejárója, mások azonban módosíthatók.
A mintaegyezés korlátai
A névtelen rekordok nem támogatják a mintaegyezést, ellentétben az elnevezett rekordokkal. Három oka van:
- A mintának egy névtelen rekord minden mezőjét figyelembe kell vennie, ellentétben a nevesített rekordtípusokkal. Ennek az az oka, hogy a névtelen rekordok nem támogatják a szerkezeti altipizálást – pontos mezőegyeztetést igényelnek.
- Az (1) miatt nincs lehetőség arra, hogy a mintaegyeztetési kifejezésben további minták legyenek, mivel az egyes különálló minták más névtelen rekordtípust jelentenek.
- A (2) miatt minden névtelen rekordminta részletesebb lenne, mint a "pont" jelölés használata.
Van egy nyílt nyelvi javaslat, amely lehetővé teszi a mintaegyezést korlátozott környezetben.
A módosíthatóság korlátozásai
Egy névtelen rekord jelenleg nem határozható meg adatokkal mutable . Van egy nyílt nyelvi javaslat a módosítható adatok engedélyezésére.
Korlátozások névtelen rekordok strukturálása esetén
Nem lehet deklarálni a névtelen struktúrákat, mint IsByRefLike vagy IsReadOnly. Van egy nyílt nyelvi javaslat a rekordokra és IsByRefLike a névtelen rekordokraIsReadOnly.