2009-07-31 7 views
6

En C#, je peux compilentmodules génériques en F #

static class Foo<T> { /* static members that use T */ } 

Le résultat est générique et n'est pas instanciable.

Quel est le code F # équivalent? module<'a> ne compile pas, et type Foo<'a> est instanciable.

Répondre

9

Les autres réponses à ce jour ont chacun une partie de l'image ...

type Foo<'a> private() =   // ' 
    static member Blah (a:'a) = // ' 
     printfn "%A" a 

est grande. Ignorez ce que Reflector génère, vous ne pouvez pas instancier cette classe à partir de l'assembly F # (puisque le constructeur est privé), donc cela fonctionne bien. F # autorise également les constructeurs statiques, la syntaxe consiste à inclure des instructions 'static let' et 'static do' dans la classe (qui fonctionnent de manière analogue à la façon dont 'let' et 'do' fonctionnent dans le cadre du constructeur principal corps pour les instances). Un exemple complet:

type Foo<'a> private() =    // ' 
    static let x = 0 
    static do printfn "Static constructor: %d" x 
    static member Blah (a:'a) =  // ' 
     printfn "%A" a 

//let r = new Foo<int>() // illegal 
printfn "Here we go!" 
Foo<int>.Blah 42 
Foo<string>.Blah "hi" 
+4

aimer le // 'tour fera à partir de maintenant – ShuggyCoUk

+0

Salut. S'il vous plaît, pardonnez mon ignorance, mais quel est le truc de //? Je regarde le code et il se comporte de la même manière, avec ou sans. Je vous remercie. – user2916547

2

Je pensais au début que ce serait à ce que vous vouliez:

type Foo<'a> private() = 
    static member Blah (a:'a) = 
     printfn "%A" a 

Être comme le pre langage C# 2.0 d'être instanciable que par réflexion ou par la classe elle-même (qui nous l'espérons ne pas faire il).

mais cela est compilé en:

[Serializable, CompilationMapping(SourceConstructFlags.ObjectType)] 
public class Foo<a> 
{ 
    internal Foo() {...} 

    public static void Blah(a a) {...} 
} 

Ce qui implique que d'autres classes dans l'ensemble f # pourrait instancier. Cependant, Brian a toujours indiqué que le compilateur f # respecte ce paramètre privé malgré le type CLR sous-jacent, ce qui signifie que la seule façon d'instancier serait par réflexion ou en utilisant quelque chose comme l'attribut InternalsVisibleTo.

Cela peut encore être acceptable pour vos besoins ...

+0

D'autres classes ne peuvent pas l'instancier; le constructeur est 'privé' à ce type F # aussi loin que F # est concerné. – Brian

+0

ah - donc f # respecte le privé au-dessus et au-dessus des restrictions réelles .net CLR ... InternalsVisibleTo le laisserait sortir du sac pour l'assemblage d'AC# encore (pas que j'indique que c'est un défaut, juste que c'est possible avec un code légal non fiable). Je vais mettre à jour la réponse acclamations – ShuggyCoUk