2016-10-13 3 views
4

Tenir compte de l'extrait de code suivant en utilisant F # 4.0, .NET 4.6:extensions de type avec une contrainte générique ne soulevant pas une erreur, ni faire ce que l'on pourrait attendre

type X<'T> = Y of 'T 

type XS = X<string> 
type XI = X<int> 

type X<'T when 'T :> string> with 
    static member X = 2 
    static member take (s: 'T) = s 

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] 
module XS = 
    let foo = 10 
    let create s = XS.Y s 
    let test = XI.take 2 // expected only string allowed, XI.take should not exist 

je me attends à l'extension du type type X<'T when 'T :> string> with soit être respecté (dans ce cas cela signifierait une erreur, car string est scellé, ou limiter 'T à string), ou pour générer une erreur de syntaxe.

Qui plus est, je peux utiliser la syntaxe suivante ainsi, ce qui serait une erreur de syntaxe dans une définition de type normal (sans with):

type X<'T> when 'T :> string with 
    static member X = 2 
    static member take (s: 'T) = s 

Je pense que la contrainte est simplement ignorée sur l'extension. Est-ce par conception? Ou est-ce censé fonctionner et si oui, comment? Je suis arrivé à tout cela en expérimentant un peu avec des extensions de type et en me demandant si je pouvais créer un ensemble spécifique de méthodes qui ne s'appliquent qu'à un type concret spécifique, ou un autre type de béton restreint (quelque chose qui peut également être fait par héritage, je sais).

+3

wow! c'est vraiment étrange! Je suis curieux de savoir quelle sera l'explication – robkuz

+2

Je suspecte que la contrainte ne s'applique qu'à la définition initiale; Les génériques .Net ne sont pas des modèles C++ qui peuvent être spécialisés; peut-être un coup d'oeil sur quel code est généré (en utilisant ILSpy par exemple) peut donner quelques indices – Sehnsucht

+3

Je ne pense pas que ce que vous écrivez dans le paramètre type de l'extension type est pris en compte. Le fait qu'aucune erreur ne soit montrée est aussi un indicateur que peu importe ce que vous mettez là n'a pas vraiment d'importance. \t Si vous souhaitez créer des extensions restreintes, écrivez la contrainte au niveau de la définition de membre. – Gustavo

Répondre

3

Je pense que le compilateur devrait rejeter votre code, mais voici quelques observations:

  1. Notez que le comportement est différent si vous utilisez une extension « extrinsèque » (par exemple en mettant la définition et l'extension dans différents modules - voir Type Extensions) - là, le compilateur marque l'extension comme une erreur.
  2. Si vous souhaitez avoir instance méthodes d'extension qui s'affichent uniquement pour certaines valeurs concrètes du paramètre type, vous pouvez utiliser une méthode d'extension C# -style (cela est également expliqué dans le lien ci-dessus). Toutefois, étant donné que C# ne prend pas en charge les membres d'extension static, il est impossible d'appliquer cette astuce à votre scénario.
+1

Merci de confirmer que c'est probablement un bug. J'ai [rapporté à F # Github ici] (https://github.com/Microsoft/visualfsharp/issues/1611), je ne savais pas que l'extension de type se comporte différemment dans un module séparé (en fait, je suis conscient, mais n'était pas hier soir;) ...) – Abel