【UiPath】GenericValue型と暗黙の型変換

GenericValue型の変数をご存じだろうか。
UiPath固有の変数で、公式ドキュメントでは以下のように説明されている。

>GenericValue 変数は、テキスト、数値、日付、または配列といった種類のデータを格納することができる変数型であり、Studio 特有のものです。
>
>GenericValue 変数は、特定のアクションを実行できるように自動的に他の型に変換されます。ただし、これらの変数の型はプロジェクトに対して常に正しく変換されるとは限らないため、使用には十分な注意が必要です。
>
>UiPath Studio には GenericValue 変数の自動変換メカニズムがあり、式を正しく定義することで、目的の結果を得ることができます。式の最初の要素は、Studio から操作するガイドラインとして使用されることを考慮してください。たとえば、2 つの GenericValue 変数を追加し、式の最初の変数が String として定義されてた場合、最初に代入された値を元に 2 つの値を結合し、文字列となります。 Integer として定義した場合の結果は、合計の値となります。

https://docs.uipath.com/ja/studio/standalone/2024.10/user-guide/uipath-proprietary-variables

当記事では、このGenericValue型とそれ以外の型を加算演算子で繋いだ場合の動作について確認していく。

## 前準備

検証用に以下のワークフローを作成する。
動作としてはシンプルで、A・B・Cの3つの変数を作り、AとBを足した（+で繋いだ）結果をCに代入し、型と値をログに出力するというもの。また、確認のためA・Bの型と値も同様にログに出力している。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/9c7faa34-0611-dd37-91d6-463a8fed0378.png)

以降、このワークフローを元に変数A・B・Cの型と規定値を変更しながら実行ログを確認する。以下の例はABC全てInt32型とし、A = 1、B = 2とした際のログである。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/f6ded0a0-4a05-9f8c-ec6a-d1105729ecf6.png)


## 文字列とGenericValue型


### 【ケース 1】 String + GenericValue

|| 変数A | 変数B | 変数C | 
|:-:|:-:|:-:|:-:|
|**型**|String|GenericValue|GenericValue|
|**値**|"123"|456|?|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/2dae4d0a-7b9b-c3b7-fb0d-4efe7cc826f0.png)

>たとえば、2 つの GenericValue 変数を追加し、式の最初の変数が String として定義されてた場合、最初に代入された値を元に 2 つの値を結合し、文字列となります。

公式ドキュメント記載のケース。
結果は`123`と`456`が連結され`123456`。
なお、変数Aの規定値`123`はダブルクォーテーションで囲わず数値として設定している。
VB.netの加算演算子では、両方の式の型がStringである場合は文字列を連結するという仕様になっており、変数BがStringに変換され連結されたと考えられる。


### 【ケース 2】GenericValue (整数) + String 

|| 変数A | 変数B | 変数C | 
|:-:|:-:|:-:|:-:|
|**型**|GenericValue|String|GenericValue|
|**値**|123|"456"|?|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/240171da-0912-7d92-923f-e8a4652566d4.png)

ケース1とは逆に変数AをGenericValue型に、変数BをString型にしている。変数Aは数値`123`を既定値にしているのは先ほどと同じ。
結果は`123`と`456`が**加算**され`579`。
先頭のGenericValue型に格納されている値が数値のためか、数値同士として演算されている。

片方の変数が数値型であり、もう片方は文字列型である場合の加算演算子の仕様は以下の通り。
>Option Strict が On である場合は、コンパイラ エラーが発生します。
Option Strict が Off である場合は、String を Double に暗黙的に変換して、加算します。


### 【ケース 3】 String + GenericValue（文字列）

|| 変数A | 変数B | 変数C | 
|:-:|:-:|:-:|:-:|
|**型**|GenericValue|String|GenericValue|
|**値**|"123"|"456"|?|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/3d190cb1-8071-ea4f-904c-16ee0a4b71d9.png)

ケース2と同様の型と値だが、変数Aの規定値をダブルクォーテーションで囲み、`"123"`としている。
結果はケース1と同様に`123456`。


### 【ケース 4】 String + GenericValue → Int32

|| 変数A | 変数B | 変数C | 
|:-:|:-:|:-:|:-:|
|**型**|String|GenericValue|Int32|
|**値**|"123"|456|?|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/3d190cb1-8071-ea4f-904c-16ee0a4b71d9.png)

変数ABはケース1と同じで、変数Cの型を数字型（Int32）に変更。
結果はケース1と同様に`123456`で、特に問題なく代入できている。

ちなみに、変数ABを両方String型、変数CをInt32型に変えると検証エラーになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/7356ad34-1d92-ba64-49c0-79b0ce4f7bee.png)


## 小数点とGenericValue型


### 【ケース 5】 Int32 + Double → Double

|| 変数A | 変数B | 変数C | 
|:-:|:-:|:-:|:-:|
|**型**|Int32|Double|Double|
|**値**|10|5.5|?|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/dcae5c73-5d50-dd87-b806-f40add09b7a1.png)

まずはGenericValue型無しでの確認。
Int32型とDouble型を加算してDouble型に代入している。
結果は`10`と`5.5`が加算され`15.5`。

また、この逆の場合（Double型をInt32型を代入）は検証エラーになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/c7cd7777-b7ef-a330-31b4-689d10de02e3.png)


### 【ケース 6】 Int32 + GenericValue → Int32

|| 変数A | 変数B | 変数C | 
|:-:|:-:|:-:|:-:|
|**型**|Int32|GenericValue|Int32|
|**値**|10|5.5|?|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/e9a53a7f-d105-ab4f-1eaa-91c27b777254.png)

ケース5から変数Bの型をGenericValue、変数Cの型をInt32に変更。
前述の通りDouble型をInt32型を代入しようとするとエラーとなるが、GenericValue型であれば少数を含む数値であってもエラーにならない。
結果は`10`と`5.5`を加算し小数点を繰り上げたのか`16`となっている。


## まとめ
ケース2やケース6あたりは直感に反した動きになるのではないだろうか。
GenericValue型は一見便利ではあるが、公式ドキュメントにも記載されているように、使用する際には十分に注意したい。


余談だが、過去のバージョンでは変数の型の初期選択肢にGenericValue型が含まれていたが、現在は除外されている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/662bf2b5-02cc-3a8d-6d11-e14582cf9fd5.png)


## 参考

https://learn.microsoft.com/ja-jp/dotnet/visual-basic/language-reference/operators/addition-operator

## 動作環境

UiPath.System.Activities 24.10.3