# Problems with referencing C# defined custom operator from F#

**URL:** <https://forums.fsharp.org/t/problems-with-referencing-c-defined-custom-operator-from-f/3401>\
**Category:** General\
**Created:** [November 7, 2023, 1:07pm UTC](https://forums.fsharp.org/t/problems-with-referencing-c-defined-custom-operator-from-f/3401 "2023-11-07T13:07:39Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![htc](https://avatars.discourse-cdn.com/v4/letter/h/a9adbd/32.png) [@htc](https://forums.fsharp.org/u/htc)\
**Post date:** [November 7, 2023, 1:07pm UTC](https://forums.fsharp.org/t/problems-with-referencing-c-defined-custom-operator-from-f/3401/1 "2023-11-07T13:07:39Z")

</div>

Dear community,

I have a problem and my preferred solution does not work:

1. Problem:  
There is a C# library with an overloaded == operator [gurobi 9.1](https://www.gurobi.com/documentation/9.1/refman/cs_oper_equal.html). I want to use this operator in F#, such as in

```auto
  let setEqual (lhs : GRBLinExpr, rhs : GRBLinExpr) =
      GRBLinExpr.(==) (lhs, rhs)

```

This fails with “FS0039 The type ‘GRBLinExpr’ does not define the field, constructor or member ‘==’.”

Also addressing it as member op\_EqualsEquals as outlined in [F# ops](https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/operator-overloading) does lead to the same error.

1. Extra information: Adding the library to a C# project shows me:

```auto
public static Gurobi.GRBTempConstr operator ==(Gurobi.GRBLinExpr lhs, Gurobi.GRBLinExpr rhs)
    Member of Gurobi.GRBLinExpr
)

```

and the following compiles

```auto
static GRBTempConstr SetEqual(GRBLinExpr lhs, GRBLinExpr rhs)
    {
      return lhs == rhs;
    }

```

1. Possible workaround: I can create an extra C# project, wrap the == operator there in a static method and reuse this method in F#. Pro: Works. Cons: extra project.

So my questions are:

a) Why does F# not allow me to use this operator? Are there some limitations to using operators from F#? The F# docs does not mention any (sorry, see “F# ops” link above, as this forum does not let me post the same link twice :-() .

b) Are there other workarounds than 3)? Maybe with reflection?

Cordially,  
htc

---

<div class="post-metadata">

**Author:** ![ntwilson](https://yyz2.discourse-cdn.com/flex030/user_avatar/forums.fsharp.org/ntwilson/32/984_2.png) [@ntwilson](https://forums.fsharp.org/u/ntwilson)\
**Post date:** [November 7, 2023, 4:44pm UTC](https://forums.fsharp.org/t/problems-with-referencing-c-defined-custom-operator-from-f/3401/2 "2023-11-07T16:44:44Z")

</div>

I think you can do it with `GRBLinExpr.op_Equality`. The table in that F# ops link of yours lists that for the `=` operator and not `==`, but for C# code, I think it uses `==` everywhere that F# uses `=`.  
At least in my testing, I can have a C# class:

```auto
public class Class1
{
  private int A;
  public Class1(int a) => A = a;
  public static bool operator ==(Class1 a, Class1 b) => a.A == b.A;
  public static bool operator !=(Class1 a, Class1 b) => a.A != b.A;
}

```

and then from F# I can do

```auto
printfn "%A" (Class1.op_Equality (Class1 6, Class1 6))

```

---

<div class="post-metadata">

**Author:** ![abelbraaksma](https://yyz2.discourse-cdn.com/flex030/user_avatar/forums.fsharp.org/abelbraaksma/32/1114_2.png) [@abelbraaksma](https://forums.fsharp.org/u/abelbraaksma)\
**Post date:** [November 15, 2023, 12:53pm UTC](https://forums.fsharp.org/t/problems-with-referencing-c-defined-custom-operator-from-f/3401/3 "2023-11-15T12:53:13Z")

</div>

I just downloaded that library you mentioned and checked the documentation from the URL you gave and keep in mind that the equality operator here **does not return a boolean**. In fact, it is a `GRBTempConstr`. In other words, if you try to use this in a context where equality is expected, it won’t work.

> a) Why does F# not allow me to use this operator?

As @ntwilson already showed, it is not the `op_EqualsEquals`, but the `op_Equality` that you are after. C# is confusing here: when C# uses `==`, it calls the `Equals` overload, or the `op_Equality`, if it is defined, not the `op_EqualsEquals`…

> Are there some limitations to using operators from F#? The F# docs does not mention any

No. So, even though the result here is not a boolean, you can use it.

* * *

It is important to realize that when you use the `=` (equality) operator in F#, it will do structural comparison. In other words, even if you have the `op_Equality` defined, this will not be called automatically.

If we slightly adjust your code, it compiles:

```auto
let setEqual (lhs: GRBLinExpr, rhs: GRBLinExpr) = 
    GRBLinExpr.(=) (lhs, rhs)

```

Or:

```auto
let setEqual (lhs: GRBLinExpr, rhs: GRBLinExpr) = 
    GRBLinExpr.op_Equality (lhs, rhs)

```

As you can see, you needed `op_Equality` here (which is what `operator (==)` compiles to from C#) and not `op_Equals` (which, btw, is not actually listed in that F# Operator list that you linked).

If we look at the compiled MSIL code in ILSpy, we see the same. The actual `operator (==)` from C# is compiled into a static member `op_Equality` and not `op_Equals`.

However, you are right in that, to map the F# operator `==` (double-equals), you need to define an operator `op_EqualsEquals`, which you can then call the same way you do for C#, if you would like that (that is, as `lhs == rhs`).

---

<div class="post-metadata">

**Author:** ![htc](https://avatars.discourse-cdn.com/v4/letter/h/a9adbd/32.png) [@htc](https://forums.fsharp.org/u/htc)\
**Post date:** [December 4, 2023, 7:25am UTC](https://forums.fsharp.org/t/problems-with-referencing-c-defined-custom-operator-from-f/3401/4 "2023-12-04T07:25:53Z")

</div>

Thanks @ntwilson! I so rarely write C# code, and fixated on translating == into F# as ==, not =. Of course I found nothing. Thanks for unblocking me!

---

<div class="post-metadata">

**Author:** ![htc](https://avatars.discourse-cdn.com/v4/letter/h/a9adbd/32.png) [@htc](https://forums.fsharp.org/u/htc)\
**Post date:** [December 4, 2023, 7:27am UTC](https://forums.fsharp.org/t/problems-with-referencing-c-defined-custom-operator-from-f/3401/5 "2023-12-04T07:27:22Z")

</div>

@abelbraaksma. Thank you for the pointer to using custom = when using F# native types (where structural comparison is automatically implemented by default). That is not the case here, but nice to remember for the next internal DSL I write.
