8

Estoy intentando crear varios métodos de extensión para un tipo genérico con destino a los parámetros de tipo genérico específicos en Fa #, pero no parece que el lenguaje sea lo que me permite:Los métodos de extensión para tipos genéricos específicos

Lo que querer hacer es algo como lo siguiente:

type IEnumerable<int> with 
    member this.foo = 
     this.ToString() 

Sin embargo, me da el error del compilador (subrayando la palabra clave int):

Identificador inesperado en nombre de tipo. Operador de infijo esperado, símbolo de cotización u otro token.

La siguiente qué trabajo, a pesar de que no se une específicamente el parámetro de tipo genérico para int, ya que quiero:

type IEnumerable<'a> with 
    member this.foo = 
     this.ToString() 

¿Hay alguna manera de lograr este objetivo en Fa # - Am I quizás solo usando la sintaxis incorrecta? De lo contrario, agradecería que alguien sugiriera una solución alternativa, tal vez utilizando restricciones de tipo en alguna parte.

Respuesta

7

Esto no es posible en la versión actual de F #, por desgracia. Consulte la pregunta relacionada here.

+0

Parece que estás en lo cierto. Gracias de cualquier manera. – Noldorin

+0

Esta función se rastrea mediante una sugerencia en la base de datos interna de errores F # "4548: Métodos de extensión de soporte para instancias de tipos específicos", pero es poco probable que se corte para la versión VS2010. – Brian

0

Bueno, puede usar restricciones, pero no con tipos sellados como int.

type IEnumerable<'a when 'a :> InheritableType> = 
member this.Blah = 
    this.ToString() 

Hmm ...

+1

Gracias por la sugerencia, pero de hecho, estoy trabajando con un tipo sellado aquí, por lo que no funciona. – Noldorin

+0

Probablemente esto no sea exactamente lo que piensas ... Definitivamente estás definiendo un nuevo tipo 'IEnumerable' - intenta llamar a la extensión en un' IEnumerable 'existente. – kvb

6

métodos de extensión genéricos están disponibles ahora en F # 3.1:

open System.Runtime.CompilerServices 
open System.Collections.Generic 

[<Extension>] 
type Utils() = 
    [<Extension>] 
    static member inline Abc(obj: IEnumerable<int>) = obj.ToString() 

printfn "%A" ([1..10].Abc()) 
0

Con el fin de ayudar a los demás en busca de soluciones similares, aquí es un ejemplo que muestra cómo utilizar los métodos de extensión con restricciones de tipo genérico. En el ejemplo siguiente, hay una restricción de tipo que requiere que el argumento de tipo pasado expone un constructor predeterminado. Esto se hace usando el atributo [<CLIMutable>] aplicado al registro Order. Además, estoy restringiendo el resultado del método al tipo pasado.

Para utilizar el método de extensión, debe especificar el tipo que desea utilizar. Tenga en cuenta que también extiendo una interfaz de diccionario genérica.

[<Extension>] 
type ExtensionMethds() = 

    [<Extension>] 
    static member inline toObject<'T when 'T: (new: unit -> 'T)> (dic: IDictionary<string,obj>): 'T = 
     let instance = new 'T() 
     // todo: set properties via reflection using the dictionary passed in 
     instance 


[<CLIMutable>] 
type Order = {id: int} 

let usage = 
    let dictionaryWithDataFromDb = dict ["id","1" :> obj] 
    let theOrder = dictionaryWithDataFromDb.toObject<Order>() 
    theOrder 
Cuestiones relacionadas