Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Aby udostępniać pola bez scalania odrębnych typów modeli, użyj rozrzutów rekordów, dostępnych począwszy od języka F# 11.
Służy ...Type do współtworzenia deklaracji pól do nowego nazwanego rekordu lub ...expression współtworzenia wartości pól do nazwanego lub anonimowego rekordu. Ponowne użycie deklaracji i mapowanie wartości to niezależne opcje.
Redagowanie typów rekordów
Aby udostępnić pola połączeń między typami konfiguracji, należy podzielić Endpoint na nową deklarację rekordu:
type Endpoint = { Host: string; Port: int }
type ClientOptions =
{ ...Endpoint
TimeoutSeconds: int }
ClientOptions ma Hostwartości , Porti TimeoutSeconds. Jest to odrębny typ nominalny, a nie Endpoint podtyp.
Wiele źródeł i jawnych deklaracji może być wyświetlanych w tej samej definicji typu:
type Logging = { LogLevel: string }
type LoggedClientOptions = { ...ClientOptions; ...Logging }
Uczestniczą tylko pola rekordów. Metody, właściwości, które nie są polami rekordów, a statyczne elementy członkowskie nie są kopiowane. Źródło może być nazwanym rekordem lub typem rekordu anonimowego, w tym skrótem dla rekordu anonimowego. Miejsce docelowe rozprzestrzeniania typu musi być nazwanym typem rekordu.
Redaguj wartości rekordów
Skopiuj punkt końcowy do opcji klienta, a następnie użyj rekordu anonimowego, aby zastąpić hosta:
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
Rozkłady wyrażeń akceptują nazwane lub anonimowe źródła rekordów i miejsca docelowe, w tym rekordy struktury. Każde pole docelowe musi otrzymać wartość. Jawna adnotacja docelowa jest przydatna, gdy kilka nazwanych typów rekordów współużytkuje etykiety.
Wzmacnianie typu pola
Późniejsza deklaracja pola może zastąpić typ pola rozłożonego. Na przykład reprezentują identyfikator analizowany za pomocą type CustomerId = CustomerId of System.Guidelementu , a następnie odróżnić zaimportowany rekord od jednego z tym identyfikatorem:
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 weryfikuje tekst; pole rozkładu kopiuje tylko pola.
CustomerId rozróżnia identyfikatory od innych identyfikatorów GUID bez nakładania dalszych reguł.
Łączenie niezależnych modeli
Utwórz deklaracje z wyselekcjonowanych rekordów nominalnych i anonimowego typu rekordu, a następnie złóż wartości z niezależnych źródeł:
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 |}
Źródła nazwane i anonimowe dostarczają ; ProductCardkarta dostarcza stan anonimowego widoku.
CanOrder jest obliczany raz, a nie obliczany ponownie, gdy później konstrukcja zmienia liczbę.
Project do znanego celu
Typ docelowy wybiera pola, które mają być zachowywane. Wiele źródeł może dostarczać zamienniki:
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 program przechowuje tylko Host i Port; production łączy źródła i jawne przesłonięcia. Jawne pola nieobecne w obiekcie docelowym pozostają błędy.
Rekord anonimowy bez adnotacji przyjmuje wszystkie pola współautora. Nazwany element docelowy musi być wywnioskowalny. Nieznane źródła wymagają własnych adnotacji, takich jak (source: ClientOptions) parametr funkcji.
Kolejność pól i przesłonięcia
Współtworzenie jest odczytywane od lewej do prawej. W przypadku powtarzającej się nazwy pola najbardziej odpowiedni wkład wygrywa. Reguła ma zastosowanie zarówno do deklaracji pól w typach, jak i do wartości pól w wyrażeniach.
let laterHost = {| Host = "db.example.com" |}
let corrected: Endpoint = { ...local; ...laterHost; Port = 5433 }
Po zastąpieniu typu podaj wartość typu zastępczego. Powtarzające się jawne pola, takie jak { Host = "first"; Host = "second" }, pozostają błędami.
W przypadku deklaracji typów zwycięskie pole pojawia się na pozycji swojego zwycięskiego udziału. Pola ze źródła zachowują kolejność źródłową. Ta kolejność ma znaczenie dla konstruktorów i zgodności podpisów.
Ocena i kopiowanie
Wyrażenia źródłowe spreadu są uruchamiane raz, w kolejności źródłowej, nawet jeśli późniejsza współtworzenie zastępuje każde podane pole:
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" ])
Rozkłady tworzą nowy rekord z płytkimi kopiami pól i tymi samymi konwersjami co jawne przypisania. Obiekty modyfikowalne, do których odwołuje się pola, pozostają współużytkowane.
Zagnieżdżone aktualizacje pól działają z rozrzutami, podobnie jak w przypadku kopiowania i aktualizowania:
let original = {| Connection = local; Retries = 3 |}
let changed = {| ...original; Connection.Port = 5433 |}
assert (changed.Connection.Port = 5433)
assert (original.Connection.Port = 5432)
Późniejszy udział w Connection zamiany wcześniejszej zagnieżdżonej aktualizacji do tego pola. Umieść celowe przesłonięcia po rozprzestrzenianiach, które powinny zostać zastąpione.
Ostrzeżenia dotyczące pól w tle
Późniejsze rozłożenie może przypadkowo cofnąć jawny wybór. Kompilator domyślnie zgłasza te ostrzeżenia:
| Warning | Meaning |
|---|---|
| FS3897 | Pole z typu rozłóż cienie wcześniejszej jawnej deklaracji pola. |
| FS3898 | Pole z wyrażenia rozkłada cienie wcześniejszego jawnego powiązania pola. |
Na przykład { Host = "db.example.com"; ...local } pobiera z Hostlocalelementu , a nie "db.example.com".
W przypadku inspekcji innych nakładających się na siebie ostrzeżeń włącz następujące ostrzeżenia dotyczące zgody:
| Warning | Meaning |
|---|---|
| FS3905 | Typ rozkłada cień pola z wcześniejszego typu rozłożonego. |
| FS3906 | Jawne pole cieniuje pole z wcześniejszego rozkładu. |
| FS3907 | Wyrażenie rozprzestrzenia pole w tle z wcześniejszego rozkładu wyrażenia. |
<WarnOn>$(WarnOn);3905;3906;3907</WarnOn>
Te uwagi nie zmieniają zachowania z prawej strony wygrywa.
Reprezentacja i zgodność interfejsu API
Typ rozdziela atrybuty pola kopiowania i atrybutów na poziomie pola. Nie kopiują atrybutów na poziomie typu; atrybut [<Struct>] miejsca docelowego określa jego reprezentację. Argumenty typu źródłowego muszą spełniać ogólne ograniczenia źródła, w tym ograniczenia jednostek miary.
Important
Używaj rozkładów typów tylko wtedy, gdy współdzielona ewolucja jest celowa. Zmiana pola źródłowego może zmieniać pola publiczne, konstruktora, atrybuty lub ograniczenia miejsca docelowego bez edytowania tego miejsca docelowego.
Spready nie pomijają kontroli ułatwień dostępu. Rekordy dopuszczane do wartości null nie są prawidłowymi źródłami rozrzutu; ustal, że wartość dopuszczana do wartości null jest niepusta przed jej użyciem. Zależności cykliczne przez spready są odrzucane. Zwykłe pola rekordów cyklicznych nie są zabronione tylko dlatego, że deklaracja używa również rozkładu.
Typ spreads działa w .fsi plikach. Podpis może używać jawnych pól, podczas gdy implementacja używa spreadów lub odwrotnie, pod warunkiem, że wynikowe pola i ich kolejność zgadzają się. Cudzysłów zawierają rozbudowaną konstrukcję rekordu, a nie węzeł rozłożony.
Wybieranie spreadów lub kopiowania i aktualizacji
Użyj wyrażeń kopiowania i aktualizacji dla aktualizacji tego samego typu z jednego źródła. Użyj rozrzutów, aby połączyć źródła, projekt do innego typu rekordu lub ponownie użyć deklaracji pól. Nie łącz with i ... w tym samym wyrażeniu rekordu.
Spready nie mają zastosowania do kolekcji, wyrażeń obiektów, dowolnych .NET obiektów ani rekordów języka C#. Nie zapewniają składni wzorca rekordu. Konstruktory rekordów są oddzielną funkcją języka F# 11.2.