Oldalpár operátorok rögzítése

Ha különböző modelltípusok egyesítése nélkül szeretne mezőket megosztani, használjon rekordpárokat, amelyek az F# 11-től érhetők el.

Meződeklarációk ...Type új névvel ellátott rekordhoz való hozzáadására vagy ...expression mezőértékek hozzáadására egy névvel ellátott vagy névtelen rekordhoz. A deklaráció újrafelhasználása és az értékleképezés független választás.

Rekordtípusok írása

A kapcsolatmezők konfigurációtípusok közötti megosztásához terjesszen át Endpoint egy új rekorddeklarációra:

type Endpoint = { Host: string; Port: int }

type ClientOptions =
    { ...Endpoint
      TimeoutSeconds: int }

ClientOptions van Host, Portés TimeoutSeconds. Ez egy különálló névleges típus, nem altípus Endpoint .

Több forrás és explicit deklaráció is megjelenhet ugyanabban a típusdefinícióban:

type Logging = { LogLevel: string }
type LoggedClientOptions = { ...ClientOptions; ...Logging }

Csak a rekordmezők vesznek részt. A metódusok, a nem rekordmezők és a statikus tagok nem másolódnak. A forrás lehet névvel ellátott rekord vagy névtelen rekordtípus, beleértve egy névtelen rekord rövidítését is. A típuspár célhelyének nevesített rekordtípusnak kell lennie.

Rekordértékek írása

Másolja a végpontot az ügyfélbeállításokba, majd használjon névtelen rekordot a gazdagép lecseréléséhez:

let local = { Host = "localhost"; Port = 5432 }
let options: ClientOptions = { ...local; TimeoutSeconds = 30 }

let remote = {| ...options; Host = "db.example.com" |}

printn $"{remote.Host}:{remote.Port}, timeout {remote.TimeoutSeconds}s"
// db.example.com:5432, timeout 30s

A kifejezéspárok névvel ellátott vagy névtelen rekordforrásokat és célhelyeket fogadnak el, beleértve a strukturált rekordokat is. Minden célmezőnek értéket kell kapnia. Egy explicit céljegyzet akkor hasznos, ha több elnevezett rekordtípus megosztja a címkéket.

Mező típusának megerősítése

Egy későbbi meződeklaráció lecserélheti az oldalpármező típusát. Jelöljön például egy elemezett azonosítót a következővel type CustomerId = CustomerId of System.Guid, majd különböztetje meg az importált rekordot az azonosítóval:

type ImportedCustomer = { Name: string; Id: string }
type IdentifiedCustomer = { ...ImportedCustomer; Id: CustomerId }

let identify (source: ImportedCustomer) =
    match Guid.TryParse source.Id with
    | true, id -> Ok ({ ...source; Id = CustomerId id }: IdentifiedCustomer)
    | false, _ -> Error "Invalid customer identifier."

Guid.TryParse ellenőrzi a szöveget; az oldalpár csak a másolt mezőket másolja. CustomerId anélkül különbözteti meg az azonosítókat a többi grafikus felhasználói felülettől, hogy további szabályokat ír elő.

Független modellek egyesítése

Deklarációk összeállítása válogatott névleges rekordból és névtelen rekordtípusból, majd értékek összeállítása független forrásokból:

type PublicProductFields = { Name: string; UnitPrice: decimal }
type ProductRow = { ...PublicProductFields; InternalCost: decimal }
type StockCounts = {| InStock: int; Reserved: int |}

type ProductCard =
    { ...PublicProductFields
      ...StockCounts
      CanOrder: bool }
let product: ProductRow =
    { Name = "Notebook"; UnitPrice = 12.50m; InternalCost = 4m }
let stock: StockCounts = {| InStock = 8; Reserved = 2 |}

let card: ProductCard =
    { ...product; ...stock; CanOrder = stock.InStock > stock.Reserved }

let viewState = {| ...card; Selected = false |}
let selected = {| ...viewState; Selected = true |}

A névvel ellátott és névtelen források adják meg az adatokat ProductCard; a kártya ezután névtelen megtekintési állapotot biztosít. CanOrder egyszer lesz kiszámítva, és nem számítja újra újra, amikor egy későbbi konstrukció módosítja a darabszámokat.

Project egy ismert célba

A céltípus kijelöli a megtartandó mezőket. Több forrás is elláthat cserét:

let endpoint: Endpoint = { ...options }
let overrides = {| Host = "db.example.com"; Port = 5433 |}
let production: ClientOptions =
    { ...options; ...overrides; TimeoutSeconds = 60 }

printn $"{endpoint.Host}:{endpoint.Port}"
printn $"{production.Host}:{production.Port}, timeout {production.TimeoutSeconds}s"
// localhost:5432
// db.example.com:5433, timeout 60s

endpoint csak Host és Port; production egyesíti a forrásokat és a explicit felülbírálásokat. A céltól hiányzó explicit mezők továbbra is hibák maradnak.

Egy névtelen rekord az összes közreműködő mezőt felveszi. A megnevezett célnak következtethetőnek kell lennie. Az ismeretlen forrásoknak saját széljegyzetekre van szükségük, például (source: ClientOptions) egy függvényparaméteren.

Mezőrend és felülbírálások

A hozzájárulások balról jobbra olvashatók. Ismétlődő mezőnév esetén a jobb szélső hozzájárulás nyer. A szabály a típusok meződeklarációira és a kifejezések mezőértékére egyaránt vonatkozik.

let laterHost = {| Host = "db.example.com" |}
let corrected: Endpoint = { ...local; ...laterHost; Port = 5433 }

A típus felülbírálása után adja meg a cseretípus értékét. Az ismétlődő explicit mezők, például { Host = "first"; Host = "second" }a hibák továbbra is megmaradnak.

Típusdeklarációk esetén egy nyertes mező jelenik meg a nyertes hozzájárulás helyén. A forrás mezői megőrzik a forrásrendjüket. Ez a sorrend a konstruktorok és az aláírások megfelelőségét érinti.

Kiértékelés és másolás

Az oldalpáros forráskifejezések egyenként, forrás sorrendben futnak, még akkor is, ha egy későbbi hozzájárulás lecseréli az általuk megadott összes mezőt:

let visits = ResizeArray<string>()
let hostFrom source host =
    visits.Add source
    {| Host = host |}

let selected =
    {| ...hostFrom "first" "localhost"
       ...hostFrom "second" "db.example.com" |}

assert (selected.Host = "db.example.com")
assert (Seq.toList visits = [ "first"; "second" ])

Az oldalpárok egy új rekordot hoznak létre sekély mezőpéldányokkal és az explicit hozzárendelésekkel megegyező átalakításokkal. A mezők által hivatkozott mutable objektumok továbbra is megosztottak maradnak.

A beágyazott mezőfrissítések ugyanúgy működnek az oldalpárokkal, mint a másolással és frissítéssel:

let original = {| Connection = local; Retries = 3 |}
let changed = {| ...original; Connection.Port = 5433 |}

assert (changed.Connection.Port = 5433)
assert (original.Connection.Port = 5432)

Egy későbbi hozzájárulás a Connection mező korábbi beágyazott frissítésének lecseréléséhez. Helyezzen szándékos felülbírálásokat a felülbírálandó oldalpárok után.

Figyelmeztetések árnyékolt mezőkkel kapcsolatban

Egy későbbi oldalpár véletlenül visszavonhat egy explicit választást. A fordító alapértelmezés szerint a következő figyelmeztetéseket jelenti:

Warning Meaning
FS3897 A típuspárok mezői egy korábbi explicit meződeklarációt árnyékként használnak.
FS3898 Egy kifejezésből származó mező árnyékolással egy korábbi explicit mezőkötést eredményez.

Például a következőt veszi fel Hostlocal, { Host = "db.example.com"; ...local } nem "db.example.com".

Egyéb átfedések naplózásához engedélyezze az alábbi opt-in figyelmeztetéseket:

Warning Meaning
FS3905 A típuspárok árnyékolással árnyékot ad egy mezőnek egy korábbi típuspárból.
FS3906 Egy explicit mező árnyékolást ad egy korábbi oldalpár mezőinek.
FS3907 Egy kifejezés egy korábbi kifejezéspár mezőinek árnyékolását jelzi.
<WarnOn>$(WarnOn);3905;3906;3907</WarnOn>

Ezek az értesítések nem változtatják meg a jobb oldali nyerési viselkedést.

Reprezentáció és API-kompatibilitás

A típuspárok másolási mező nem módosíthatók és mezőszintű attribútumok. Nem másolnak típusszintű attribútumokat; a cél saját [<Struct>] attribútuma határozza meg a reprezentációját. A forrástípus argumentumainak meg kell felelniük a forrás általános korlátozásainak, beleértve a mértékegység-megkötéseket is.

Important

Típuspárokat csak akkor használjon, ha a közös evolúció szándékos. A forrásmező módosítása módosíthatja a cél nyilvános mezőit, konstruktorát, attribútumait vagy kényszereit anélkül, hogy az adott célhelyet szerkesztené.

Az oldalpárok nem kerülik meg az akadálymentességi ellenőrzéseket. A null értékű rekordok érvénytelen szórási források; annak használata előtt állapítsa meg, hogy a null értékű értékek nem null értékűek. A rendszer elutasítja a ciklikus függőségeket a spreadeken keresztül . A hagyományos rekurzív rekordmezők nem tilthatók csak azért, mert a deklaráció spreadet is használ.

Típuspárok a fájlokban .fsi működnek. Az aláírások explicit mezőket használhatnak, miközben a megvalósítás oldalpárokat vagy fordítottakat használ, feltéve, hogy az eredményül kapott mezők és azok sorrendje megegyezik. Az idézőjelek a kidolgozott rekordszerkezetet tartalmazzák, nem az oldalpárcsomópontot.

Oldalpárok vagy másolás és frissítés kiválasztása

Egy forrásból származó azonos típusú frissítéshez használjon másolási és frissítési kifejezéseket . Oldalpárok használatával egyesítheti a forrásokat, más rekordtípusra vetítheti a projektet, vagy újra felhasználhatja a meződeklarációkat. Ne egyesítse with és ... ne használja ugyanabban a rekordkifejezésben.

Az oldalpárok nem vonatkoznak gyűjteményekre, objektumkifejezésekre, tetszőleges .NET objektumokra vagy C# rekordokra. Nem adnak meg rekordmintaszintaxist. A rekordkonstruktorok egy különálló F# 11.2-funkció.

Lásd még