2016-12-26 6 views
5

Ich entwickle F# Anwendung .net 4.6.1 auf VS2015. Ich habe Methoden:F # Methode gibt null statt Option

type CommonHelper = 
    static member SideEffectOnNull act x = if x = null then act(); x else x 
    static member SideEffectOnNotNull act x = if x <> null then act(); x else x 

...

static member GetPerformanceCounter (fname: CounterFullName) = 

     let getCounterInternal (counterFullName: CounterFullName) = 
      Log.Information("Getting counter: {category}\\{name}\\{instance} ", counterFullName.Category, counterFullName.Name, counterFullName.Instance) 
      let receivedCategory = PerformanceCounterCategory.GetCategories().FirstOrDefault(fun x -> String.Equals(x.CategoryName, counterFullName.Category.Category, StringComparison.InvariantCultureIgnoreCase)) 
      if receivedCategory = null then 
       Serilog.Log.Warning ("Category not found: {category}", counterFullName.Category); null 
      else 
       let receivedCounters = PerforrmanceCounterProxy.GetPerformanceCountersFromCategoryOrNull counterFullName.Instance receivedCategory 
       if receivedCounters = null then 
        Log.Warning ("Instance not found {name}(instance: {instance}) in category {category}", counterFullName.Name, counterFullName.Instance, counterFullName.Category); null 
       else 
        receivedCounters.FirstOrDefault(fun y -> String.Equals(y.CounterName, counterFullName.Name.Name, StringComparison.InvariantCultureIgnoreCase)) 
        |> CommonHelper.SideEffectOnNull (fun unit -> Log.Warning ("Name {name}(instance: {instance}) not found for category {category}", counterFullName.Name, counterFullName.Instance, counterFullName.Category)) 

     getCounterInternal fname 
     |> CommonHelper.SideEffectOnNull (fun unit ->Log.Warning("Getting counter failed: {category}\\{name}\\{instance}", fname.Category, fname.Name, fname.Instance)) 
     |> CommonHelper.SideEffectOnNotNull (fun unit ->Log.Information("Getting Counter secceed: {category}\\{name}\\{instance}", fname.Category, fname.Name, fname.Instance)) 
     |> (fun x -> if x = null then None else Option.Some(x)) 

Aber wenn ich diese Methode aufrufen i erhalten null statt option. enter image description here Was mache ich falsch?

+2

Meine Vermutung - das Problem im Zusammenhang mit "Visual Studio 2015". Da die Geschäftslogik gut funktioniert, denke ich, dass die VS2015-Benutzeroberfläche falsche Informationen anzeigt. – burzhuy

+2

Ich habe den Standardwert für diesen Typ beim Durchlaufen angezeigt - "default (T)" im Falle von Werttypen und "null" für Referenztypen. – Asti

Antwort

9

In F # ist es möglich, einen datenlosen Wert eines DU mit der Konstante null zur Laufzeit darzustellen. Sie können die Compiler anweisen, so mit CompilationRepresentationFlags.UseNullAsTrueValue zu tun:

[<CompilationRepresentation(CompilationRepresentationFlags.UseNullAsTrueValue)>] 
type A = B | C of int 

printfn "%A" (obj.ReferenceEquals(B, null)) // will print "true" 

In dem obigen Code, der DU-Wert B wird zu null zusammengestellt. Dies ist manchmal zu Optimierungszwecken nützlich: Anstatt jedes Mal eine Instanz zuzuweisen, verwende ich eine Konstante. Hilft, wenn der Wert viel verwendet wird.

So ist der Option Typ verwendet die gleiche Technik für den None Fall, und deshalb None als null im Debugger zeigt nach oben.

Eines Tages wird der Debugger über geeignete Erweiterungspunkte verfügen, um diese und andere F # -Features zu implementieren. Bis dahin spricht der Debugger C#, und Sie können die Übersetzung machen.

+2

Der Debugger hat vor VS2015 funktioniert, was ist passiert? – scrwtp

+1

Willst du damit sagen, dass der Debugger vor 2015 "None" anstelle von "null" gezeigt hat? Bist du dir absolut sicher? –

+1

Nur überprüft und du hast Recht. Ich muss mental "Nones" durch "Nullen" ersetzt haben. – scrwtp