35
29

More than 5 years have passed since last update.

(.NET)Parse,TryParseの罠

Last updated at Posted at 2015-02-07

はじめに

上級プログラマーの知識としては常識(忘れている場合も多々ある :sweat: )ですが、初心プログラマにはよく陥る罠です。
この罠の知識があれば、この罠が原因で例外が発生しているのかなと想像つきます。
 正直なところ、自分自身への戒めの意味もあります :weary:

たまに発生する例外

 一般向けアプリを作成し、500名位に1名位の割合で、プログラム起動時、設定ファイル読み込み時に例外が発生します。開発環境で実証テストを行っても発生せず。「環境依存じゃないの?」とか「Windows Updateが当たってないんじゃないのか?」等とユーザーの環境に原因があるような事で済まされる可能性があります。

地域設定を確認せよ

 その時、ユーザーのPCの地域設定パネルの形式を確認して下さい。「日本語(日本)」になってますか?
1.png

あるユーザさんは何故か「アイスランド語(アイスランド)」になってました。
形式がこの設定になっていると、小数点が「.」(ドット)でなく「,」(カンマ)になります。
2.png

カンの良い方ならピーンときますが、設定ファイルから読み込み処理を行う時に、小数点の解釈ができずに例外が発生するのです。

おいおいバグじゃん :ant:

コードは以下のようになってました

(バグ発生コード)
var stringValue = "2.54";         //ファイルから読み込んだと仮定する
var decimalValue = default(decimal);
decimal.TryParse(stringValue, out decimalValue);

 上記のように簡単に文字列→数値変換を行うと、Parse() または TryParse()で解釈する文字列は、地域設定のコントロールパネルの設定に影響されます。
 初心者プログラマは気にせず上記のコードを作成しがちです。2つの引数でParse()を呼び出すのは禁止にした方が良いかも知れません。

対策

 地域設定の影響を受けないようにするためには、以下のように InvariantCulture を明示的に指定して、Parse()を行うべきです。

(正しいコード)
var stringValue = "2.54";         //ファイルから読み込んだと仮定する
var decimalValue = default(decimal);
decimal.TryParse(stringValue ,
                 NumberStyles.Number,
                 System.Globalization.CultureInfo.InvariantCulture,
                 out decimalValue );

コーディング規約に謳おう!

現場では、拡張メソッドにして、Parsr()TryParse()使用禁止を謳った方が良いと思います。

(拡張メソッド)
/// <summary>
/// 文字列→decimal
/// </summary>
/// <param name="stringValue">文字列</param>
/// <param name="defaultValue">失敗時の数値</param>
/// <returns>解析されたdecimal値</returns>
static public decimal ToDecimal(this string stringValue, decimal defaultValue = decimal.Zero)
{
    var value = defaultValue;
    if (decimal.TryParse(stringValue, NumberStyles.Number, 
                         System.Globalization.CultureInfo.InvariantCulture, out value))
    {
        return value;
    }
    return defaultValue;
}
35
29
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
29