How to call custom operator with Reflection
Asked Answered
C

4

33

In my small project I'm using System.Reflection classes to produce executable code. I need to call the + operator of a custom type. Does anybody know how can I call customized operator of custom class using C# reflection?

Colangelo answered 20/6, 2012 at 5:22 Comment(0)
S
52

C# compiler converts overloaded operator to functions with name op_XXXX where XXXX is the operation. For example, operator + is compiled as op_Addition.

Here is the full list of overloadable operators and their respective method names:

┌──────────────────────────┬───────────────────────┬──────────────────────────┐
│         Operator         │      Method Name      │       Description        │
├──────────────────────────┼───────────────────────┼──────────────────────────┤
│ operator +               │ op_UnaryPlus          │ Unary                    │
│ operator -               │ op_UnaryNegation      │ Unary                    │
│ operator ++              │ op_Increment          │ Unary                    │
│ operator --              │ op_Decrement          │ Unary                    │
│ operator !               │ op_LogicalNot         │ Unary                    │
│ operator +               │ op_Addition           │                          │
│ operator -               │ op_Subtraction        │                          │
│ operator *               │ op_Multiply           │                          │
│ operator /               │ op_Division           │                          │
│ operator &               │ op_BitwiseAnd         │                          │
│ operator |               │ op_BitwiseOr          │                          │
│ operator ^               │ op_ExclusiveOr        │                          │
│ operator ~               │ op_OnesComplement     │ Unary                    │
│ operator ==              │ op_Equality           │                          │
│ operator !=              │ op_Inequality         │                          │
│ operator <               │ op_LessThan           │                          │
│ operator >               │ op_GreaterThan        │                          │
│ operator <=              │ op_LessThanOrEqual    │                          │
│ operator >=              │ op_GreaterThanOrEqual │                          │
│ operator <<              │ op_LeftShift          │                          │
│ operator >>              │ op_RightShift         │                          │
│ operator %               │ op_Modulus            │                          │
│ implicit operator <type> │ op_Implicit           │ Implicit type conversion │
│ explicit operator <type> │ op_Explicit           │ Explicit type conversion │
│ operator true            │ op_True               │                          │
│ operator false           │ op_False              │                          │
└──────────────────────────┴───────────────────────┴──────────────────────────┘

So to retrieve the operator+ method of the DateTime struct, you need to write:

MethodInfo mi = typeof(DateTime).GetMethod("op_Addition",
    BindingFlags.Static | BindingFlags.Public );
Stale answered 20/6, 2012 at 5:43 Comment(9)
Just curious :) What if I have a static op_Addition method with the same signature?Dockery
@ŞafakGür Then you'll get a compiler error saying "Type '<YourTypeName>' already defines a member called 'op_Addition' with the same parameter types". Because the defined operator method is exactly renamed to aforementioned name, you cannot have both in the same class.Stale
And what would be the naming rule for casting operators?Mcdougall
I've managed to find it out myself, but for future reference: casting operators are named op_Explicit and op_Implicit (I think these names are self-explanatory). Remember though that multiple casting operators can be defined, so one will need to narrow down the search by specifying either parameter type or return type (in respect to the 'direction' of cast).Mcdougall
Did you forgot ~ ?Remanent
@wishmaster35 Apparently! :) Will add it.Stale
Out of curiosity, did you find this from a book or doc reference or somehow inspect the C# compiler? Thanks!Arboriculture
@ChristabellaIrwanto I remember that I first decompiled a C# code, and later looked up the actual code in the C# compiler. This is not documented anywhere by MS.Stale
@MohammadDehghan thank you for your valuable insight :)Arboriculture
V
8
typeof(A).GetMethod("op_Addition").Invoke(null, instance1, instance2);
Vigilance answered 20/6, 2012 at 5:37 Comment(1)
by me, parameters needs to be given via an array type.GetMethod("op_Subtraction").Invoke(null, new object[] { instance1, instance2 });Wabash
E
0

Consider to make your customized operator as property of your Class. And then access the property and its value through reflection.

like

PropertyInfo pinfo = obj.GetType().GetProperty("CustomOperator", BindingFlags.Public | BindingFlags.Instance);
string customOperator = pinfo.GetValue(obj,null) as string;
Ellynellynn answered 20/6, 2012 at 5:32 Comment(0)
M
0

Adding the indexer operator [] to the accepted answer.

There is a difference between non array types and array types:

Non array types

For Non array types, it is implemented as a public instance property named Item that takes an extra argument for the index (something that is allowed in general IL and VB.Net but not in C#).

In other words, when calling SetValue or GetValue on the PropertyInfo (returned by GetProperty()) you have to use the overload that also takes an index.

Similarly when trying to use the underlying get and set methods you need to remember that their signature has one more argument compared to standard properties.

Even when using the indexer from VB.Net code you have the use the .Item property as the indexer operator is not available in VB.Net.

Array Types

Array types do not have the above Item property (besides as an explicit implementation for IList) instead there are two public methods called Get and Set (note that these are only available on the actual array type not the base System.Array type, however there are other GetValue() and SetValue() methods available there).

Mer answered 12/2 at 19:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.