2015-03-15 6 views
2

Почему у F # замыкания есть атрибут [<Serializable>]? Что было бы практическим прецедентом?Почему F # закрывает сериализуемым?

Этот код демонстрирует сериализации и десериализации окончания:

open System 
open System.IO 
open System.Runtime.Serialization.Formatters.Binary 

let formatter = BinaryFormatter() 
let addTwo = (+) 2 

(addTwo.GetType()).GetCustomAttributes false 
|> Array.iter (fun attribute -> 
    printfn "Closure has attribute: %s" (attribute.GetType()).Name 
) 

let serializedClosure = 
    use memStream = new MemoryStream() 
    formatter.Serialize (memStream, addTwo) 
    memStream.ToArray() 

Array.length serializedClosure 
|> printfn "Serialized closure length: %d bytes" 

let deserializedClosure = 
    use memStream = new MemoryStream (serializedClosure) 
    formatter.Deserialize memStream :?> Int32 -> Int32 

deserializedClosure 3 
|> printfn "Invoking deserialized closure: 2 + 3 = %d" 

printfn "Press any key to exit..." 
Console.ReadKey true |> ignore 

Это работает, потому что закрытие компилируется в класс (обратите внимание на serializable ключевое слово:

.class nested assembly auto ansi serializable beforefieldinit [email protected] 
    extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32, int32> 
{ 
    .method assembly specialname rtspecialname instance void .ctor() cil managed {...} 
    .method public strict virtual instance int32 Invoke (int32 y) cil managed {...} 
} 

С именами закрытия (как [email protected]) полностью зависимы от компилятора и меняются даже при небольшом изменении кода, мне было интересно, что является обоснованием создания сериализуемых замыканий?

+0

это еще не закрытие - это просто функция ... действительно, большие проблемы возникают, как только начинают использовать закрытие внутри;) - но спасибо за вопрос - я не знал, что FSharpFunc сериализуем: D – Carsten

+0

@ CarstenKönig, ну, ты прав. Но когда я компилирую код в режиме отладки, он определенно является закрытием, потому что '' 2 'еще не встроен и имя класса заканчивается на '' clo'' ;; –

ответ

1

Я думаю, что ответ заключается в том, что маркировка класса serializable не имеет никакого отрицательного воздействия и его можно безопасно игнорировать. Не отмечая класс как serializable, было бы невозможно его сериализовать (если кто-то нашел для этого хорошее применение). Итак, компилятор просто выбирает, возможно, более полезное значение по умолчанию.

Действительно ли это используется? Ну, если у вас есть один и тот же двоичный файл, работающий на нескольких машинах и разговаривающий друг с другом с использованием двоичной сериализации, то вы, , могли бы фактически передавать функции таким образом. Я не думаю, что кто-то на самом деле это делает (MBrace использует более сложный механизм), но это был бы вариант (или это был бы вариант, когда бинарная сериализация .NET была бы классной :-)).

Смежные вопросы