If you were to define some extension methods, properties in an assembly written in F#, and then use that assembly in C#, would you see the defined extensions in C#?
For some reason, the accepted answer suggests using reflection to get an F# type extension method. Since the compiled method name is different between versions of F#, and may be different depending on arguments, inlining and other naming related issues, I would rather suggest using CompiledNameAttribute instead, which is much easier and blends in easily with C#. Besides, no reflection (and its performance and type safety issues) necessary.
Suppose you have this in F#:
namespace Foo.Bar
module StringExt =
type System.String with
static member ToInteger s = System.Int64.Parse(s)
You wouldn't be able to call this directly and the compiled version would look like this (depending on whether or not there are overloads):
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);
}
}
Unless you would use reflection, you can't access the method String.ToInteger.Static. However, a simple method decoration with the CompiledNameAttribute solves this problem:
namespace Foo.Bar
module StringExt =
type System.String with
[]
static member ToInteger s = System.Int64.Parse(s)
Now the compiled method looks like this in Reflector, mark the change in the compiled name:
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);
}
}
You can still use this method the way you are used to in F# (as String.ToInteger in this case). But more importantly, you can now use this method without reflection or other trickery from C#:
var int x = Foo.Bar.StringExt.ToInteger("123");
And of course, you can make your life simpler by adding a type alias in C# for the Foo.Bar.StringExt module:
using Ext = Foo.Bar.StringExt;
....
var int x = Ext.ToInteger("123");
This is not the same as an extension method, and decorating the static member with a System.Runtime.CompilerServices.Extension attribute gets ignored. This is merely a simple way to use type extensions from other .NET languages. If you want a "genuine" extension method that appears to act on the type, use the let-syntax from the other answers here.