7

decimal?オブジェクトをデータ型にキャストする単一行の方法はありますか?

私のコードは次のようになります。

foreach(DataRow row in dt.Rows)
{
    var a = new ClassA()
    {
         PropertyA = row["ValueA"] as decimal?,   
         PropertyB = row["ValueB"] as decimal?,
         PropertyC = row["ValueC"] as decimal?
    };

    // Do something

}

ただし、オブジェクトをにキャストするとdecimal?、期待どおりに機能せず、毎回nullが返されます。

データ行はExcelファイルから読み取られるため、各行のオブジェクトのデータ型doubleは、値がある場合はa、string空白のままの場合はnullのいずれかになります。

このキャストを実行するための推奨される方法はを使用することですdecimal.TryParse、クラスのすべての10進数プロパティに対して一時変数を作成したくありません(実際のクラスには、3ではなく10進数である約7つのプロパティがあります)。

decimal tmpvalue;
decimal? result = decimal.TryParse((string)value, out tmpvalue) ?
                  tmpvalue : (decimal?)null;

nullの可能性のある値を1行でにキャストする方法はありますdecimal?か?

ここに投稿された回答を試しましたが、機能していないようで、が返さnullれるため、値も表示されます。row["ValueA"] as stringnull

4

7 に答える 7

6

最善の策は、拡張メソッドを作成することです。decimal?これは私が使用しているものですが、代わりに返すように微調整することができます。

public static class ObjectExtensions
{
    public static decimal ToDecimal(this object number)
    {
        decimal value;
        if (number == null) return 0;
        if (decimal.TryParse(number.ToString().Replace("$", "").Replace(",", ""), out value))
            return value;
        else
            return 0;
    }
    public static decimal? ToNullableDecimal(this object number)
    {
        decimal value;
        if (number == null) return null;
        if (decimal.TryParse(number.ToString().Replace("$", "").Replace(",", ""), out value))
            return value;
        else
            return null;
    }

}

.ToDecimal()次に、を呼び出すのと同じ方法で、任意のオブジェクトを呼び出すことによってそれを使用します.ToString()

これは1行ではありませんが、使用された時点での単一の関数呼び出しであり、非常に再利用可能です。

null許容バージョンを追加するために編集

于 2013-01-02T17:40:01.483 に答える
4

doubleとして読み取る値がある場合、それ以外の場合は文字列だと思います

さて、これは問題を複雑にします。解析する必要がある場合とそうでない場合があるからです。

最初に実行したいのは、それがすでにaであるかどうかを確認してdoubleキャストすることです。これは、キャストは解析よりもはるかに安価だからです。構文解析には費用がかかります。

このロジックは自明ではないため、独自のメソッドに属します。

public static deciaml? getDecimal(object rawValue)
{
    decimal finalValue;

    double? doubleValue = rawValue as double?;
    if(doubleValue.HasValue)
        return (decimal) doubleValue.Value;
    else if(decimal.TryParse(rawValue as string, out finalValue))
    {
        return finalValue;
    }
    else
    {
        return null;//could also throw an exception if you wanted.
    }
}

常にdoubleになることがわかっていて、文字列値が必要ない場合は、さらに簡単です。その場合、最初にそれをdoubleにキャストする必要があります。これは実際のタイプであるため、次に、簡単に10進数に変換できます。

PropertyA = (decimal?)(row["ValueA"] as double?);
于 2013-01-02T17:43:12.340 に答える
1

decimal.TryParse行く方法です。ヘルパーメソッドを作成して値を返すだけです。あなたが言及したのとほぼ同じコード:

private decimal? convertToNullableDecimal(object value){
  decimal tmpvalue;
  return decimal.TryParse((string)value, out tmpvalue) ? tmpvalue : (decimal?)null;
}

アップデート

これは、null許容の10進数が必要であることを前提としています。それ以外の場合は、他の回答で提案されているように、組み込みの方法を使用してください。Convert.ToDecimal

于 2013-01-02T17:40:24.037 に答える
0

次のようなものを試してください

Func<object, decimal?> l_convert =
    (o) => decimal.TryParse((o ?? "").ToString(), out tmpvalue) ? tmpvalue : (decimal?)null;

var a = new ClassA()
{
     PropertyA = l_convert(row["ValueA"]),   
     PropertyB = l_convert(row["ValueB"]),
     PropertyC = l_convert(row["ValueC"])
};
于 2013-01-02T17:41:01.337 に答える
0

お役に立てれば

decimal temp;
foreach(DataRow row in dt.Rows)
{
    var a = new ClassA()
    {
         PropertyA = Decimal.TryParse(row["ValueA"].ToString(), out temp) ? Convert.ToDecimal(row["ValueA"].ToString()) : (Decimal?) null,   
         ....
    };

    // Do something

}
于 2013-01-02T17:42:36.023 に答える
0

Decimal.Parseメソッドを試すことができます。

public static decimal ToDecimal(this string value){

    try
    {
        return Decimal.Parse(value);
    }   
    catch (Exception)
    {
        //  catch FormatException, NullException
        return 0;
    }
}

//  use
PropertyA = row["ValueA"].ToString().ToDecimal();
PropertyB = row["ValueB"].ToString().ToDecimal();
PropertyC = row["ValueC"].ToString().ToDecimal();
于 2013-01-02T17:47:23.533 に答える
0

Convert.ToDecimal(object)ほとんどあなたが望むことをします。double値を適切に(最初に文字列に移動せずに)変換し、10進数に変換できる他のタイプも処理します。うまくいかないことの1つは、null変換(またはString.Emptyからnullへの変換)です。これは、拡張メソッドで処理しようとします。

public static class ObjectToDecimal
{
  public static decimal? ToNullableDecimal(this object obj)
  {
    if(obj == null) return null;
    if(obj is string && String.Empty.Equals(obj)) return null;
    return Convert.ToDecimal(obj);
  }
}

Convert.ToDecimal(object)例外がスローされる可能性があることを覚えておいてください。そのため、注意する必要があります。

于 2013-01-02T18:14:25.477 に答える