Jeśli miałbyś zdefiniować niektóre metody rozszerzania, właściwości w zespole napisane w F #, a następnie użyć tego zestawu w C#, czy widziałbyś zdefiniowane rozszerzenia w C#?F # metody rozszerzenia w C#
Jeśli tak, to byłoby takie fajne.
Jeśli miałbyś zdefiniować niektóre metody rozszerzania, właściwości w zespole napisane w F #, a następnie użyć tego zestawu w C#, czy widziałbyś zdefiniowane rozszerzenia w C#?F # metody rozszerzenia w C#
Jeśli tak, to byłoby takie fajne.
[<System.Runtime.CompilerServices.Extension>]
module Methods =
[<System.Runtime.CompilerServices.Extension>]
let Exists(opt : string option) =
match opt with
| Some _ -> true
| None -> false
Ta metoda może być używana tylko w języku C# przez dodanie przestrzeni nazw (przy użyciu przy użyciu) do pliku, w którym będzie używana.
if (p2.Description.Exists()) { ...}
Here is a link to the original blogpost.
Odpowiadając na pytanie w komentarzach "Rozbudowa Metody statyczne":
namespace ExtensionFSharp
module CollectionExtensions =
type System.Linq.Enumerable with
static member RangeChar(first:char, last:char) =
{first .. last}
w F # to nazwać tak:
open System.Linq
open ExtensionFSharp.CollectionExtensions
let rangeChar = Enumerable.RangeChar('a', 'z')
printfn "Contains %i items" rangeChar.CountItems
W języku C# to nazwać jak więc:
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);
}
}
}
A teraz daj mi mój szalony medal!
Dzięki, ale co z właściwościami rozszerzeń instancji i metodami statycznymi oraz właściwościami statycznych rozszerzeń? Czy oni też zostaną wezwani? Powodem, dla którego o to pytałem jest to, ponieważ wiem, że C# ma tylko metody rozszerzenia instancji. –
Dzięki, właśnie zobaczyłem twoją aktualizację. –
Zdecydowanie zasługujesz na medal za kreatywną drogę z refleksją i być może w 2009 roku był to jedyny sposób. Jednak możesz teraz użyć ['CompiledNameAttribute'] (http://stackoverflow.com/a/39678801/111575) dla znacznie prostszego i bezpieczniejszego podejścia do wywoływania F # z C#. – Abel
Per ze language spec, rozdział 10.7 "rozszerzeń typu":
opcjonalne członkowie przedłużające są cukier syntaktyczny dla członków statycznych. Zastosowania opcjonalnych elementów rozszerzeń rozwijają się do wywołań statycznych członków o zakodowanych nazwach, gdzie obiekt jest przekazywany jako pierwszy argument. Kodowanie nazw nie jest określone w tym wydaniu F # i nie jest kompatybilne z kodowaniami C# z członków rozszerzenia C#
Pomimo mojej drugiej odpowiedzi, po prostu próbowałem tego z F # CTP (na powłoce VS) i C# Express z moje okno w domu (! Wszystkie bezpłatnych narzędzi dev), a to działa:
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
}
}
nie byłem świadomy można to zrobić; sprytny. Podziękowania dla @alex.
Dzięki, ale czy nie jest to tylko metoda rozszerzenia instancji? –
Dzięki, byłem bardziej zainteresowany innymi rozszerzeniami F #, aby pokazać się w C#, ale twój inny rodzaj adresów odpowiedzi, które. –
Z jakiegoś powodu przyjęta odpowiedź sugeruje użycie odbicia, aby uzyskać metodę rozszerzenia typu F #. Ponieważ nazwa skompilowanej metody jest różna w różnych wersjach F # i może być różna w zależności od argumentów, inliningu i innych kwestii związanych z nazewnictwem, wolałbym raczej zaproponować użycie CompiledNameAttribute
, co jest znacznie łatwiejsze i łatwo wtapia się w C#. Poza tym nie ma potrzeby refleksji (i jej wydajności oraz kwestii bezpieczeństwa typu).
Załóżmy, że masz to w F #:
namespace Foo.Bar
module StringExt =
type System.String with
static member ToInteger s = System.Int64.Parse(s)
nie byłaby w stanie wywołać tego bezpośrednio, a wersja skompilowana będzie wyglądać następująco (w zależności od tego, czy występują przeciążenia):
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);
}
}
Jeśli nie używasz odbicia, nie możesz uzyskać dostępu do metody String.ToInteger.Static
.Jednak prosta metoda dekoracji z CompiledNameAttribute
rozwiązuje ten problem:
namespace Foo.Bar
module StringExt =
type System.String with
[<CompiledName("ToInteger")>]
static member ToInteger s = System.Int64.Parse(s)
Teraz skompilowany metoda wygląda to w reflektor zaznaczyć zmiany w skompilowanej nazwa:
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);
}
}
można nadal korzystać z tego sposób w jaki jesteś przyzwyczajony w F # (jako String.ToInteger
w tym przypadku). Ale co ważniejsze, można teraz korzystać z tej metody bez refleksji lub innego oszustwa z C#:
var int x = Foo.Bar.StringExt.ToInteger("123");
I oczywiście, można uczynić swoje życie prostszym dodając typ aliasu w C# dla modułu Foo.Bar.StringExt
:
using Ext = Foo.Bar.StringExt;
....
var int x = Ext.ToInteger("123");
To nie jest to samo co metoda rozszerzenia, a dekorowanie elementu statycznego atrybutem System.Runtime.CompilerServices.Extension
zostaje zignorowane. Jest to po prostu prosty sposób użycia type extensions z innych języków .NET. Jeśli chcesz "prawdziwą" metodę rozszerzenia, która wydaje się działać na typ, użyj let
-syntax z innych odpowiedzi tutaj.
Zobacz także http://cs.hubfs.net/forums/thread/13967.aspx – Brian