Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Pokud chcete sdílet pole bez sloučení různých typů modelů, použijte rozložení záznamů, která jsou k dispozici od F# 11.
Slouží ...Type k přispívání deklarací polí do nového pojmenovaného záznamu nebo ...expression k přispívání hodnot polí do pojmenovaného nebo anonymního záznamu. Opakované použití deklarace a mapování hodnot jsou nezávislé volby.
Psaní typů záznamů
Pokud chcete sdílet propojovací pole mezi typy konfigurace, rozprostřete Endpoint do nové deklarace záznamu:
type Endpoint = { Host: string; Port: int }
type ClientOptions =
{ ...Endpoint
TimeoutSeconds: int }
ClientOptions má Host, Porta TimeoutSeconds. Jedná se o odlišný jmenovitý typ, nikoli Endpoint podtyp.
Ve stejné definici typu se může zobrazit více zdrojů a explicitních deklarací:
type Logging = { LogLevel: string }
type LoggedClientOptions = { ...ClientOptions; ...Logging }
Účastní se jenom pole záznamů. Metody, vlastnosti, které nejsou záznamem polí, a statické členy se nekopírují. Zdrojem může být pojmenovaný záznam nebo anonymní typ záznamu, včetně zkratky pro anonymní záznam. Cílem rozložení typu musí být pojmenovaný typ záznamu.
Vytvoření hodnot záznamu
Zkopírujte koncový bod do možností klienta a pak pomocí anonymního záznamu nahraďte hostitele:
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
Rozložení výrazu přijímají pojmenované nebo anonymní zdroje záznamů a cíle, včetně záznamů struktury. Každé cílové pole musí obdržet hodnotu. Explicitní cílová poznámka je užitečná, když několik pojmenovaných typů záznamů sdílí popisky.
Posílení typu pole
Pozdější deklarace pole může nahradit typ rozprostřeného pole. Například představuje analyzovaný identifikátor a type CustomerId = CustomerId of System.Guidpak odliší importovaný záznam od záznamu s tímto identifikátorem:
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 ověří text; rozložení kopíruje pouze pole.
CustomerId rozlišuje identifikátory od jiných identifikátorů GUID bez uložení dalších pravidel.
Kombinování nezávislých modelů
Vytvořte deklarace z kurátorovaného nominálního záznamu a anonymního typu záznamu a pak sestavte hodnoty z nezávislých zdrojů:
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 |}
Pojmenované a anonymní zdroje poskytují ProductCard; karta pak poskytuje stav anonymního zobrazení.
CanOrder se vypočítá jednou, nepřepočítá se, když pozdější konstrukce změní počty.
Project do známého cíle
Cílový typ vybere pole, která chcete zachovat. Nahrazování může poskytovat více zdrojů:
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 uchovává pouze Host a Port; production kombinuje zdroje a explicitní přepsání. Explicitní pole chybí v cíli, zůstávají chyby.
Neanotovaný anonymní záznam přebírá všechna pole, která přispěla. Pojmenovaný cíl musí být odvozený. Neznámé zdroje potřebují vlastní poznámky, například (source: ClientOptions) u parametru funkce.
Pořadí polí a přepsání
Příspěvky se čtou zleva doprava. U opakovaného názvu pole vyhraje příspěvek nejvíce vpravo. Pravidlo se vztahuje jak na deklarace polí v typech, tak na hodnoty polí ve výrazech.
let laterHost = {| Host = "db.example.com" |}
let corrected: Endpoint = { ...local; ...laterHost; Port = 5433 }
Po přepsání typu zadejte hodnotu náhradního typu. Opakované explicitní pole, například { Host = "first"; Host = "second" }, zůstávají chyby.
Pro deklarace typu se výherní pole zobrazí na pozici svého vítězného příspěvku. Pole ze zdroje si zachovají své zdrojové pořadí. Toto pořadí záleží na konstruktorech a souladu s podpisem.
Vyhodnocení a kopírování
Rozprostření zdrojových výrazů se spouští jednou za sekundu ve zdrojovém pořadí, i když pozdější příspěvek nahradí každé pole, které poskytují:
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" ])
Rozložení vytvoří nový záznam s kopiemi mělkých polí a stejnými převody jako explicitní přiřazení. Proměnlivé objekty odkazované podle polí zůstanou sdílené.
Aktualizace vnořených polí fungují s rozprostřením, jak to dělají s kopírováním a aktualizací:
let original = {| Connection = local; Retries = 3 |}
let changed = {| ...original; Connection.Port = 5433 |}
assert (changed.Connection.Port = 5433)
assert (original.Connection.Port = 5432)
Pozdější příspěvek, který Connection nahradí dřívější vnořenou aktualizaci do daného pole. Po rozprostřených rozloženích umístěte záměrná přepsání.
Upozornění týkající se stínovaných polí
Pozdější šíření může omylem vrátit zpět explicitní volbu. Kompilátor ve výchozím nastavení hlásí tato upozornění:
| Warning | Meaning |
|---|---|
| FS3897 | Pole z typu rozprostře stínuje dřívější explicitní deklaraci pole. |
| FS3898 | Pole zvýrazho |
Například { Host = "db.example.com"; ...local } přebírá Host z local, ne "db.example.com".
V případě auditu jiných překrývajících se událostí povolte tato upozornění výslovného souhlasu:
| Warning | Meaning |
|---|---|
| FS3905 | Typ rozprostře stínuje pole z dřívějšího rozložení typu. |
| FS3906 | Explicitní pole stínuje pole z dřívějšího rozložení. |
| FS3907 | Výraz rozprostře stínuje pole z dřívějšího rozložení výrazu. |
<WarnOn>$(WarnOn);3905;3906;3907</WarnOn>
Tato oznámení nemění chování wins nejvíce vpravo.
Kompatibilita reprezentace a rozhraní API
Type spreads copy field mutability and field-level attributes. Nekopírovají atributy na úrovni typu; Vlastní [<Struct>] atribut cíle určuje jeho reprezentaci. Argumenty typu zdroje musí splňovat obecná omezení zdroje, včetně omezení měrných jednotek.
Important
Použití šíření typu pouze v případech, kdy je úmyslný sdílený vývoj. Změna zdrojového pole může změnit veřejná pole cíle, konstruktor, atributy nebo omezení bez úprav v daném cíli.
Šíření neodejdou kontroly přístupnosti. Záznamy s možnou hodnotou null nejsou platné zdroje šíření; navázat, že hodnota s možnou hodnotou null je před použitím nenulová. Cyklické závislosti prostřednictvím šíření jsou odmítnuty . Běžná rekurzivní pole záznamů nejsou zakázána pouze proto, že deklarace používá také rozložení.
Rozložení typu funguje v .fsi souborech. Podpis může použít explicitní pole, zatímco implementace používá rozložení nebo obráceně za předpokladu, že výsledná pole a jejich pořadí souhlasí. Uvozovky obsahují propracovanou konstrukci záznamů, nikoli rozprostřený uzel.
Volba rozložení nebo kopírování a aktualizace
Pro aktualizaci stejného typu z jednoho zdroje použijte výrazy copy-and-update . Pomocí rozložení můžete kombinovat zdroje, projektovat do jiného typu záznamu nebo znovu použít deklarace polí. Nekombinujte with ani ... ve stejném výrazu záznamu.
Šíření se nevztahují na kolekce, výrazy objektů, libovolné .NET objekty ani záznamy jazyka C#. Nezadají syntaxi vzorů záznamů. Konstruktory záznamů jsou samostatnou funkcí F# 11.2.