Estensioni di tipo (F#)
Le estensioni dei tipi consentono di aggiungere nuovi membri a un tipo di oggetto definito in precedenza.
// Intrinsic extension.
type typename with
member self-identifier.member-name =
body
...
[ end ]
// Optional extension.
type typename with
member self-identifier.member-name =
body
...
[ end ]
Note
Vi sono due forme di estensioni, con sintassi e comportamento leggermente diversi.Un'estensione intrinseca è un'estensione inclusa nello stesso spazio dei nomi o modulo, nello stesso file di origine e nello stesso assembly (DLL o file eseguibile) del tipo esteso.Un'estensione facoltativa è un'estensione che si trova al di fuori del modulo, dello spazio dei nomi o dell'assembly originale del tipo esteso.Le estensioni intrinseche appaiono nel tipo quando il tipo viene esaminato tramite reflection, mentre le estensioni facoltative no.Le estensioni facoltative devono trovarsi nei moduli e sono incluse nell'ambito solo quando il modulo che contiene l'estensione è aperto.
Nella sintassi precedente typename rappresenta il tipo esteso.Qualsiasi tipo a cui è possibile accedere può essere esteso, ma il nome del tipo deve essere un nome di tipo effettivo, non un'abbreviazione del tipo.È possibile definire più membri in un'estensione del tipo.L'elemento self-identifier rappresenta l'istanza dell'oggetto richiamato, come nei normali membri.
La parola chiave end è facoltativa nella sintassi leggera.
I membri definiti nelle estensioni del tipo possono essere utilizzati come gli altri membri in un tipo di classe.Analogamente agli altri membri, possono essere membri statici o di istanza.Questi metodi sono noti anche come metodi di estensione, le proprietà sono note come proprietà di estensione e così via.I membri delle estensioni facoltative vengono compilati in membri statici per i quali l'istanza dell'oggetto viene passata in modo implicito come primo parametro.Tuttavia, agiscono come se fossero membri di istanza o membri statici a seconda di come vengono dichiarati.I membri impliciti delle estensioni sono inclusi come membri del tipo e possono essere utilizzati senza restrizione.
I metodi di estensione non possono essere metodi virtuali o astratti.Possono eseguire l'overload di altri metodi dello stesso nome, ma il compilatore assegna la priorità ai metodi di estensione nel caso di una chiamata ambigua.
Se per un tipo sono presenti più estensioni di tipo intrinseche, tutti i membri devono essere univoci.Per le estensioni di tipo facoltative, i membri delle diverse estensioni di tipo per uno stesso tipo possono avere nomi uguali.Si verificano errori di ambiguità solo se il codice client apre due ambiti diversi che definiscono gli stessi nomi di membro.
Nell'esempio seguente un tipo in un modulo ha un'estensione di tipo intrinseca.Per il codice client esterno al modulo, l'estensione di tipo appare come normale membro del tipo a tutti gli effetti.
module MyModule1 =
// Define a type.
type MyClass() =
member this.F() = 100
// Define type extension.
type MyClass with
member this.G() = 200
module MyModule2 =
let function1 (obj1: MyModule1.MyClass) =
// Call an ordinary method.
printfn "%d" (obj1.F())
// Call the extension method.
printfn "%d" (obj1.G())
È possibile utilizzare estensioni di tipo intrinseche per separare la definizione di un tipo in sezioni.Questa operazione può essere utile nella gestione di definizioni del tipo di grandi dimensioni, ad esempio per tenere il codice generato dal compilatore separato dal codice creato dallo sviluppatore o per raggruppare il codice creato da persone diverse o associato a funzionalità diverse.
Nell'esempio seguente viene utilizzata un'estensione di tipo facoltativa per estendere il tipo System.Int32 con un metodo di estensione FromString che chiama il membro statico Parse.Il metodo testFromString indica che il nuovo membro viene chiamato come qualsiasi membro di istanza.
// Define a new member method FromString on the type Int32.
type System.Int32 with
member this.FromString( s : string ) =
System.Int32.Parse(s)
let testFromString str =
let mutable i = 0
// Use the extension method.
i <- i.FromString(str)
printfn "%d" i
testFromString "500"
Il nuovo membro di istanza apparirà come qualsiasi altro metodo del tipo Int32 in IntelliSense, ma solo quando il modulo che contiene l'estensione è aperto o incluso in altro modo nell'ambito.