F # 4,5 ' deki yeniliklerWhat's new in F# 4.5

F # 4,5, F # diline birden çok geliştirme ekler.F# 4.5 adds multiple improvements to the F# language. Bu özelliklerin birçoğu, F # ' ta verimli kod yazmanızı sağlamak için birlikte eklenmiştir ve ayrıca bu kodun güvenli olmasını sağlar.Many of these features were added together to enable you to write efficient code in F# while also ensuring this code is safe. Bunun yapılması, bu yapılar kullanılırken dile birkaç kavram ve önemli miktarda derleyici analizini ekleme anlamına gelir.Doing so means adding a few concepts to the language and a significant amount of compiler analysis when using these constructs.

başlarkenGet started

F # 4,5 tüm .NET Core dağıtımları ve Visual Studio Araçları 'nda mevcuttur.F# 4.5 is available in all .NET Core distributions and Visual Studio tooling. Daha fazla bilgi edinmek için F # ile çalışmaya başlayın.Get started with F# to learn more.

Span ve ByRef benzeri yapılarSpan and byref-like structs

Span<T>.NET Core 'da tanıtılan tür, artık f # 4,5 ile başlayan f # ' da izin verilen kesin olarak belirlenmiş bir şekilde bellekteki arabellekleri temsil etmenize olanak tanır.The Span<T> type introduced in .NET Core allows you to represent buffers in memory in a strongly typed manner, which is now allowed in F# starting with F# 4.5. Aşağıdaki örnek, Span<T> farklı arabellek temsilleri ile bir üzerinde çalışan bir işlevi nasıl yeniden kullanabileceğinizi gösterir:The following example shows how you can re-use a function operating on a Span<T> with different buffer representations:

let safeSum (bytes: Span<byte>) =
    let mutable sum = 0
    for i in 0 .. bytes.Length - 1 do
        sum <- sum + int bytes.[i]
    sum

// managed memory
let arrayMemory = Array.zeroCreate<byte>(100)
let arraySpan = new Span<byte>(arrayMemory)

safeSum(arraySpan) |> printfn "res = %d"

// native memory
let nativeMemory = Marshal.AllocHGlobal(100);
let nativeSpan = new Span<byte>(nativeMemory.ToPointer(), 100)

safeSum(nativeSpan) |> printfn "res = %d"
Marshal.FreeHGlobal(nativeMemory)

// stack memory
let mem = NativePtr.stackalloc<byte>(100)
let mem2 = mem |> NativePtr.toVoidPtr
let stackSpan = Span<byte>(mem2, 100)

safeSum(stackSpan) |> printfn "res = %d"

Bunun önemli bir yönü, yayılma ve diğer ByRef benzeri yapıların , kullanımlarını beklenmedik şekilde bulacağınız yöntemlerle sınırlayan, derleyicinin gerçekleştirdiği çok rigıd statik analizine sahip olmasını sağlar.An important aspect to this is that Span and other byref-like structs have very rigid static analysis performed by the compiler that restrict their usage in ways you might find to be unexpected. Bu, F # 4,5 ' de sunulan performans, ifade ve güvenlik arasındaki temel zorunluluğunu getirir.This is the fundamental tradeoff between performance, expressiveness, and safety that is introduced in F# 4.5.

Revaed ByRef 'lerRevamped byrefs

F # 4,5 ' den önce, F # ' ta Byrefs güvenli değildi ve çok sayıda uygulama için ses geri alındı.Prior to F# 4.5, Byrefs in F# were unsafe and unsound for numerous applications. F # 4,5 ' de ve ayrıca, span ve ByRef benzeri yapılar için yapılan aynı statik analizler de, ByRef 'ler etrafında ses sorunları ele alındı.Soundness issues around byrefs have been addressed in F# 4.5 and the same static analysis done for span and byref-like structs was also applied.

ınref< 'T> ve outref< 'T>inref<'T> and outref<'T>

Salt okunurdur, salt yazılır ve okuma/yazma yönetilen işaretçisinin kavramını göstermek için F # 4,5, inref<'T> outref<'T> sırasıyla salt okunurdur ve salt yazılır işaretçileri temsil edecek olan türleri tanıtır.To represent the notion of a read-only, write-only, and read/write managed pointer, F# 4.5 introduces the inref<'T>, outref<'T> types to represent read-only and write-only pointers, respectively. Her birinin farklı anlamları vardır.Each have different semantics. Örneğin, bir öğesine yazamaz inref<'T> :For example, you cannot write to an inref<'T>:

let f (dt: inref<DateTime>) =
    dt <- DateTime.Now // ERROR - cannot write to an inref!

Varsayılan olarak, tür çıkarımı, inref<'T> zaten değişebilir olarak bildirilmemiş olmadığı sürece, yönetilen işaretçileri gerçek F # kodu ile satır içinde olacak şekilde çıkarmış olur.By default, type inference will infer managed pointers as inref<'T> to be in line with the immutable nature of F# code, unless something has already been declared as mutable. Bir şeyi yazılabilir yapmak için, mutable adresini onu işleyen bir işleve veya üyeye geçirmeden önce bir tür bildirmeniz gerekir.To make something writable, you'll need to declare a type as mutable before passing its address to a function or member that manipulates it. Daha fazla bilgi için bkz. Byrefs.To learn more, see Byrefs.

ReadOnly yapılarReadonly structs

F # 4,5 ile başlayarak, bir yapısına şu şekilde açıklama ekleyebilirsiniz IsReadOnlyAttribute :Starting with F# 4.5, you can annotate a struct with IsReadOnlyAttribute as such:

[<IsReadOnly; Struct>]
type S(count1: int, count2: int) =
    member x.Count1 = count1
    member x.Count2 = count2

Bu, yapıda kesilebilir üye bildirmesinin yanı sıra F # ve C# ' nin bir derlemeden tüketilirken onu ReadOnly olarak görmesini sağlayan meta verileri yayar.This disallows you from declaring a mutable member in the struct and emits metadata that allows F# and C# to treat it as readonly when consumed from an assembly. Daha fazla bilgi için bkz. ReadOnly yapılar.To learn more, see ReadOnly structs.

Void işaretçileriVoid pointers

voidptrTürü, aşağıdaki işlevlerde olduğu gibi F # 4,5 ' a eklenir:The voidptr type is added to F# 4.5, as are the following functions:

  • NativePtr.ofVoidPtrvoid işaretçiyi yerel bir int işaretçisine dönüştürmek içinNativePtr.ofVoidPtr to convert a void pointer into a native int pointer
  • NativePtr.toVoidPtrYerel bir int işaretçisini void işaretçiye dönüştürmek içinNativePtr.toVoidPtr to convert a native int pointer to a void pointer

Bu, void işaretçilerin kullanıldığı bir yerel bileşenle birlikte çalışırken yararlıdır.This is helpful when interoperating with a native component that makes use of void pointers.

match! anahtar sözcüğüThe match! keyword

match!Anahtar sözcüğü, bir hesaplama ifadesi içindeyken model eşleştirmeyi geliştirir:The match! keyword enhances pattern matching when inside a computation expression:

// Code that returns an asynchronous option
let checkBananaAsync (s: string) =
    async {
        if s = "banana" then
            return Some s
        else
            return None
    }

// Now you can use 'match!'
let funcWithString (s: string) =
    async {
        match! checkBananaAsync s with
        | Some bananaString -> printfn "It's banana!"
        | None -> printfn "%s" s
}

Bu, genellikle zaman uyumsuz gibi hesaplama ifadelerle seçenekleri (veya diğer türleri) kapsayan kodu kısaltmaya olanak tanır.This allows you to shorten code that often involves mixing options (or other types) with computation expressions such as async. Daha fazla bilgi için bkz. Match!.To learn more, see match!.

Dizi, liste ve dizi ifadelerinde gevşek yukarı atama gereksinimleriRelaxed upcasting requirements in array, list, and sequence expressions

Dizi, liste ve sıra ifadeleri içindeki başka bir diğerinin devraldığı türlerin karıştırma, genellikle türetilmiş herhangi bir türü ya da ile üst türüne yukarı atama yapmak için gereklidir :> upcast .Mixing types where one may inherit from another inside of array, list, and sequence expressions has traditionally required you to upcast any derived type to its parent type with :> or upcast. Bu, aşağıda gösterildiği gibi gevşek bir şekilde yapılır:This is now relaxed, demonstrated as follows:

let x0 : obj list  = [ "a" ] // ok pre-F# 4.5
let x1 : obj list  = [ "a"; "b" ] // ok pre-F# 4.5
let x2 : obj list  = [ yield "a" :> obj ] // ok pre-F# 4.5

let x3 : obj list  = [ yield "a" ] // Now ok for F# 4.5, and can replace x2

Dizi ve liste ifadeleri için girinti ayırmaIndentation relaxation for array and list expressions

F # 4,5 ' den önce, yöntem çağrılarına bağımsız değişken olarak geçirildiğinde dizi ve liste ifadelerini aşırı girintilendirmek gerekir.Prior to F# 4.5, you needed to excessively indent array and list expressions when passed as arguments to method calls. Bu artık gerekli değildir:This is no longer required:

module NoExcessiveIndenting =
    System.Console.WriteLine(format="{0}", arg = [|
        "hello"
    |])
    System.Console.WriteLine([|
        "hello"
    |])