[C#]演算子のオーバーロードとプリミティブ型

#はじめに

演算子のオーバーロードはop_xxxというメソッドが内部で定義されるようですが、int型などはこのメソッドを持っていません。
ILの仕様と言われればそれまでですが、ILの仕様を熟知していないので、とりあえず実験してみました。
Type.IsPrimitiveと何か関係があるのかなと思い、組み合わせて検証しました。


いい感じの検索ワードが思いつかず検証してみたので、（なんの役に立つのかはわかりませんが、）自分用のメモとして残します。

#環境
Windows 10
Visual Studio 2019

#参考

プリミティブ型について
https://ufcpp.net/blog/2016/12/tipsprimitives/

#検証1

```OP.cs
foreach (var t in types) {
	bool haveOverloadOperator = t.GetMethods().Count(x => x.Name.StartsWith("op_")) > 0;
	Console.WriteLine($"{t.Name} : {t.IsPrimitive} : {haveOverloadOperator}");
}
```

```Result
Boolean : True : False
Byte : True : False
SByte : True : False
Int16 : True : False
UInt16 : True : False
Int32 : True : False
UInt32 : True : False
Int64 : True : False
UInt64 : True : False
IntPtr : True : True
UIntPtr : True : True
Char : True : False
Double : True : True
Single : True : True
Decimal : False : True
Object : False : False
String : False : True
DateTime : False : True
TimeSpan : False : True
```

op_から始まるメソッドを持っているかどうかのチェックですが、Int16などの整数型はメソッドop_で始まるメソッドがないという、少し意外な結果となりました。

#検証2
```OP.cs
foreach (var t in types) {
	List<MethodInfo> OverloadOperators = t.GetMethods().Where(x => x.Name.StartsWith("op_")).ToList();
	foreach (var m in OverloadOperators) {
		Console.WriteLine($"{t.Name} : {m.Name}");
	}
}
```

```Result
IntPtr : op_Explicit
IntPtr : op_Explicit
IntPtr : op_Explicit
IntPtr : op_Explicit
IntPtr : op_Explicit
IntPtr : op_Explicit
IntPtr : op_Equality
IntPtr : op_Inequality
IntPtr : op_Addition
IntPtr : op_Subtraction
UIntPtr : op_Explicit
UIntPtr : op_Explicit
UIntPtr : op_Explicit
UIntPtr : op_Explicit
UIntPtr : op_Explicit
UIntPtr : op_Explicit
UIntPtr : op_Equality
UIntPtr : op_Inequality
UIntPtr : op_Addition
UIntPtr : op_Subtraction
Double : op_Equality
Double : op_Inequality
Double : op_LessThan
Double : op_GreaterThan
Double : op_LessThanOrEqual
Double : op_GreaterThanOrEqual
Single : op_Equality
Single : op_Inequality
Single : op_LessThan
Single : op_GreaterThan
Single : op_LessThanOrEqual
Single : op_GreaterThanOrEqual
Decimal : op_Implicit
Decimal : op_Implicit
Decimal : op_Implicit
Decimal : op_Implicit
Decimal : op_Implicit
Decimal : op_Implicit
Decimal : op_Implicit
Decimal : op_Implicit
Decimal : op_Implicit
Decimal : op_Explicit
Decimal : op_Explicit
Decimal : op_Explicit
Decimal : op_Explicit
Decimal : op_Explicit
Decimal : op_Explicit
Decimal : op_Explicit
Decimal : op_Explicit
Decimal : op_Explicit
Decimal : op_Explicit
Decimal : op_Explicit
Decimal : op_Explicit
Decimal : op_Explicit
Decimal : op_UnaryPlus
Decimal : op_UnaryNegation
Decimal : op_Increment
Decimal : op_Decrement
Decimal : op_Addition
Decimal : op_Subtraction
Decimal : op_Multiply
Decimal : op_Division
Decimal : op_Modulus
Decimal : op_Equality
Decimal : op_Inequality
Decimal : op_LessThan
Decimal : op_LessThanOrEqual
Decimal : op_GreaterThan
Decimal : op_GreaterThanOrEqual
String : op_Equality
String : op_Inequality
DateTime : op_Addition
DateTime : op_Subtraction
DateTime : op_Subtraction
DateTime : op_Equality
DateTime : op_Inequality
DateTime : op_LessThan
DateTime : op_LessThanOrEqual
DateTime : op_GreaterThan
DateTime : op_GreaterThanOrEqual
TimeSpan : op_UnaryNegation
TimeSpan : op_Subtraction
TimeSpan : op_UnaryPlus
TimeSpan : op_Addition
TimeSpan : op_Equality
TimeSpan : op_Inequality
TimeSpan : op_LessThan
TimeSpan : op_LessThanOrEqual
TimeSpan : op_GreaterThan
TimeSpan : op_GreaterThanOrEqual
```

列挙してみると、キャストも含まれていました。。。

doubleやstringに、足し算を意味する"op_Addition"がありません。
整数や浮動小数点数はオーバーロードではなく、コンパイラがILの専用命令に変換しているからop_Additionは不要のようです。
また、参考のリンク先によるとstringの+は文字列連結のconcatに変換されるらしいので、オーバーロードとして定義されていません。

###追伸

ここまでくれば、ILの仕様もしくはコンパイル後のILを覗いてみればいいような気がします。
機会があればILを見てみたいと思います。