2012-05-03 8 views
5

Esto es realmente extraño y me temo que acabo de hacer algo tonto pero no puedo entenderlo.F # no pasa ninguno para funcionar, obteniendo nulo como valor de parámetro

estoy pasando None a la función some como el primer parámetro pero cuando la función se ejecuta, el valor de parentNode es nulo (No estoy preocupado con ella la impresión nulo para None, el valor del parámetro función es nula no None) Termino obteniendo un error de referencia nulo en la línea de función de impresión porque parentNode es nulo. Intenté tuplar los argumentos y cambiar el orden, pero eso no ayudó. Tengo la sospecha de que esto tiene algo que ver con el currículum, pero estoy perdido ...

Tuve que reemplazar el valor de la URL real con una cadena vacía por cuestiones de la empresa, pero es una url para una xsd si eso ayuda

Aquí está el código:

#light 
open System 
open System.Xml 
open System.Net 
open System.Collections.Generic 

type StartResult = 
    | Parameters of XsdParserParameters 
    | Xsd of Xsd 

and Xsd(text) = 
    let rows = new List<string>() 

    member this.Text 
     with get() = text 

    member this.Rows 
     with get() = rows 

and XsdParserParameters() = 
    let mutable url = "" 

    member this.Url 
     with get() = url 
     and set(value) = url <- value 

    member this.Start() = 
     try 
      use client = new WebClient() 
      let xsd = client.DownloadString(this.Url) 
      StartResult.Xsd(Xsd(xsd)) 
     with e -> 
      StartResult.Parameters(this) 

let processor() = 
    let parameters = XsdParserParameters() 
    parameters.Url <- "" 
    match parameters.Start() with 
    | StartResult.Parameters(xpparams) -> 
     //some error 
     () 
    | StartResult.Xsd(xsd) -> 

     let rec some (parentNode : XmlNode option) (node : XmlNode) = 
      let a =() 

      for subNode in node.ChildNodes do 
       match subNode.LocalName with 
       | "complexType" -> 
        xsd.Rows.Add(
         sprintf 
          "%O~%s~%d~%d~%s~%s~%O" 
          parentNode 
          subNode.Value 
          1 
          1 
          (subNode.Attributes.GetNamedItem("name").Value) 
          "" 
          false) 
        some (Some(subNode)) subNode 
       | "sequence" -> 
        some parentNode subNode 
       | "element" -> 
        xsd.Rows.Add(
         sprintf 
          "%O~%s~%d~%d~%s~%s~%O" 
          parentNode 
          subNode.Value 
          1 
          1 
          (subNode.Attributes.GetNamedItem("name").Value) 
          "" 
          false) 
        some (Some(subNode)) subNode 
       | _ -> 
        () 

     let xdoc = new XmlDocument(); 
     xdoc.LoadXml(xsd.Text) 

     some (None) (xdoc.DocumentElement) 

processor() 

printfn "Done..." 
Console.ReadLine() |> ignore 
+0

¿En qué línea obtiene una excepción de referencia nula? 'sprintf"% O "null' debería funcionar bien, y no veo ninguna otra referencia a' parentNode', ¿está seguro de que de allí viene el error? – Guvante

Respuesta

4

Por desgracia, es la forma F # imprime None:

> sprintf "%O" None;; 
val it : string = "<null>" 

Usted puede escribir una costumbre sprintf función para option tipo, por ejemplo:

let sprintOption v = 
    if Option.isNone v then "None" else sprintf "%A" v 
+0

Eso está bien y esperado. el problema es que el primer parámetro no obtiene "ninguno", se vuelve nulo. Actualicé mi pregunta para aclarar – Brad

4

Option<'T> (source on Github) utiliza el atributo [<CompilationRepresentation([CompilationRepresentationFlags.UseNullAsTrueValue)>] que hace que el caso nullary (None, en este caso) a ser representado por null en tiempo de ejecución.

+0

¿Por qué funciona esto?> Printfn "% O" None ;; ? ¿Debería salir ese error con una referencia nula también? ¿Y qué hay de las declaraciones de los partidos? ¿Puedo hacer coincidir ninguno, nulo o ambos? – Brad

+1

@Brad: Porque 'printf' busca nulo e imprime" "antes de intentar llamar a' ToString() '. Esto también funciona: 'printfn"% O "null'. – Daniel

+0

@rad: Sí, puede coincidir en 'None' /' null'. – Daniel

Cuestiones relacionadas