Si vous deviez définir des méthodes d'extension, des propriétés dans un assembly écrites en F #, puis utiliser cet assembly en C#, verriez-vous les extensions définies en C#?Méthodes d'extension F # en C#
Si oui, ce serait tellement cool.
Si vous deviez définir des méthodes d'extension, des propriétés dans un assembly écrites en F #, puis utiliser cet assembly en C#, verriez-vous les extensions définies en C#?Méthodes d'extension F # en C#
Si oui, ce serait tellement cool.
[<System.Runtime.CompilerServices.Extension>]
module Methods =
[<System.Runtime.CompilerServices.Extension>]
let Exists(opt : string option) =
match opt with
| Some _ -> true
| None -> false
Cette méthode pourrait être utilisée en C# uniquement en ajoutant l'espace de noms (using using) au fichier où il sera utilisé.
if (p2.Description.Exists()) { ...}
Here is a link to the original blogpost.
Répondre à la question dans les commentaires "Extension Méthodes statiques":
namespace ExtensionFSharp
module CollectionExtensions =
type System.Linq.Enumerable with
static member RangeChar(first:char, last:char) =
{first .. last}
En F # vous l'appelez comme ceci:
open System.Linq
open ExtensionFSharp.CollectionExtensions
let rangeChar = Enumerable.RangeChar('a', 'z')
printfn "Contains %i items" rangeChar.CountItems
En C# vous l'appelez comme ainsi:
using System;
using System.Collections.Generic;
using ExtensionFSharp;
class Program
{
static void Main(string[] args)
{
var method = typeof (CollectionExtensions).GetMethod("Enumerable.RangeChar.2.static");
var rangeChar = (IEnumerable<char>) method.Invoke(null, new object[] {'a', 'z'});
foreach (var c in rangeChar)
{
Console.WriteLine(c);
}
}
}
Maintenant, donnez-moi ma médaille!
Merci, mais qu'en est-il des propriétés d'extension d'instance et des méthodes statiques, ainsi que des propriétés d'extension statique? Seraient-ils appelés aussi? La raison pour laquelle j'ai posé cette question est parce que, je sais que C# a seulement des méthodes d'extension d'instance. –
Merci, viens de voir ta mise à jour. –
Vous méritez certainement une médaille pour la créativité avec la réflexion et peut-être en 2009 c'était la seule façon. Cependant, vous pouvez maintenant utiliser ['CompiledNameAttribute'] (http://stackoverflow.com/a/39678801/111575) pour une approche beaucoup plus simple et sécurisée pour appeler F # à partir de C#. – Abel
par les language spec, l'article 10.7 "extensions de type":
membres d'extension en option sont le sucre syntaxique pour les membres statiques. Les utilisations de membres d'extension optionnels élaborent des appels à des membres statiques avec des noms codés où l'objet est passé en premier argument. L'encodage des noms n'est pas spécifié dans cette version de F # et n'est pas compatible avec les encodages C# des membres d'extension C#
Savez-vous s'il est prévu d'unifier les moyens d'implémentation des extensions de type F # et C#? Ce serait bien si l'on n'avait pas besoin d'utiliser les attributs supplémentaires. – Joh
Il ne semble pas que nous fassions cela pour la première version de F # (par exemple, pas dans le calendrier VS2010). – Brian
Malgré mon autre réponse, je l'ai juste essayé avec le CTP F # (sur VS shell) et C# Express de ma boîte à la maison (! tous ses outils de développement), et cela fonctionne:
F #
#light
namespace MyFSharp
// C# way
[<System.Runtime.CompilerServices.Extension>]
module ExtensionMethods =
[<System.Runtime.CompilerServices.Extension>]
let Great(s : System.String) = "Great"
// F# way
type System.String with
member this.Awesome() = "Awesome"
let example = "foo".Awesome()
C#
using System;
using MyFSharp; // reference the F# dll
class Program
{
static void Main(string[] args)
{
var s = "foo";
//s.Awesome(); // no
Console.WriteLine(s.Great()); // yes
}
}
Je ne savais pas que vous pouvez le faire; chouette. Crédit à @alex.
Merci, mais n'est-ce pas juste une méthode d'extension d'instance? –
Merci, j'étais plus intéressé par d'autres extensions de F # à apparaître en C#, mais votre autre réponse sorte d'adresses qui. –
Pour une raison quelconque, la réponse acceptée suggère d'utiliser la réflexion pour obtenir une méthode d'extension de type F #. Puisque le nom de la méthode compilée est différent entre les versions de F #, et peut être différent selon les arguments, inlining et autres problèmes liés au nommage, je suggère plutôt d'utiliser CompiledNameAttribute
à la place, ce qui est beaucoup plus facile et se confond facilement avec C#. En outre, aucune réflexion (et ses problèmes de performance et de sécurité) n'est nécessaire.
Supposons que vous ayez ceci en F #:
namespace Foo.Bar
module StringExt =
type System.String with
static member ToInteger s = System.Int64.Parse(s)
Vous ne seriez pas en mesure d'appeler cela directement et la version compilée ressemblerait à ceci (selon si oui ou non il y a des surcharges):
namespace Foo.Bar
{
using Microsoft.FSharp.Core;
using System;
[CompilationMapping(SourceConstructFlags.Module)]
public static class StringExt
{
public static long String.ToInteger.Static(string s) =>
long.Parse(s);
}
}
Si vous n'utilisez pas la réflexion, vous ne pouvez pas accéder à la méthode String.ToInteger.Static
.Cependant, une décoration simple méthode avec le CompiledNameAttribute
résout ce problème:
namespace Foo.Bar
module StringExt =
type System.String with
[<CompiledName("ToInteger")>]
static member ToInteger s = System.Int64.Parse(s)
Maintenant, la méthode compilée ressemble à ceci dans le réflecteur, marquer le changement de nom compilé:
namespace Foo.Bar
{
using Microsoft.FSharp.Core;
using System;
[CompilationMapping(SourceConstructFlags.Module)]
public static class StringExt
{
[CompilationSourceName("ToInteger")]
public static long ToInteger(string s) =>
long.Parse(s);
}
}
Vous pouvez toujours utiliser cette méthode comme vous êtes habitué à F # (comme String.ToInteger
dans ce cas). Mais plus important encore, vous pouvez maintenant utiliser cette méthode sans réflexion ou autre supercherie de C#:
var int x = Foo.Bar.StringExt.ToInteger("123");
Et bien sûr, vous pouvez vous rendre la vie plus simple en ajoutant un alias de type en C# pour le module Foo.Bar.StringExt
:
using Ext = Foo.Bar.StringExt;
....
var int x = Ext.ToInteger("123");
Ce n'est pas la même chose qu'une méthode d'extension, et la décoration du membre statique avec un attribut System.Runtime.CompilerServices.Extension
est ignorée. C'est simplement un moyen simple d'utiliser type extensions à partir d'autres langages .NET. Si vous voulez une méthode d'extension "authentique" qui semble agir sur le type, utilisez la syntaxe let
des autres réponses ici.
Voir aussi http://cs.hubfs.net/forums/thread/13967.aspx – Brian