2009-10-07 5 views
10

私が持っているアプリケーションでは、値を動的にロードされる型に変換するために、Convert.ChangeTypeを頻繁に呼び出しています。Convert.ChangeTypeの高速版

しかし、ANTSを使用してプロファイリングしたところ、このConvert.ChangeTypeは(かなり頻繁に呼び出されるため)かなりの時間がかかるようです。誰かがこれを行うより速い選択肢を持っていますか?

この時点では、ターゲットを含むタイプオブジェクトと、その値を含むstringがあります。

以下は問題のコードです。私は、型の切り替えステートメントを実行することを検討していました(型の限られたコレクションなので)。そして、解析メソッドを呼び出すことも考えましたが、高速化が必要かどうかはわかりません。

if(attributeRow["Value"]!=DBNull.Value) 
    sample[attr] = attr.AttributeType == typeof(Guid) 
       ? new Guid(attributeRow["Value"].ToString()) 
       : (IComparable)Convert.ChangeType(attributeRow["Value"],attr.AttributeType); 

答えて

9

私はConvert.ChangeType機能(と明示的なキャスト)以外のタイプを変更するために、フレームワーク自体の他の機能に気づいていません。

これを改善する唯一の方法は、特定の状況(可能な場合)に合わせて特別に最適化された独自のChangeType関数をロールすることです。

あなたは、限られた数のタイプで作業していると言いますが、おそらくあなたは他のタイプよりも1つのタイプを扱っていますか?そうです、あなたのChangeType関数は、この特定の変換を最初に試みるように最適化することができ、失敗した場合にのみ他のものを試すことができます。スイッチスタイルのコードブロックを試してみましょう。これと同じアプローチ(最も頻繁に使用されるタイプを最初に試してみてください)をそれに適用することができます。それが速くなるかどうかは、処理しているデータ(および変換元のタイプの頻度/可変性)に依存します。これを実際に測定する唯一の方法は、それを試してプロファイルすることですConvert.ChangeType方法論との比較。あなたはロール自分で自分のための機能を探しているなら

一つの興味深いリンクはピーター・ジョンソンのブログである:

Convert.ChangeType doesn't handle nullables

もポストにコメントのすべてを必ずお読みください。

+0

私たちはいくつかの点を検討するつもりですが、この投稿は可能な限り最良の方法でやっていることを恐れているので、私はこの回答を受け入れています。 – Erich

+0

リンクで提供されるChangeTypeは完全に機能します!ありがとう! – Larry

0

静的なCスタイルのキャストだけのChangeType関数をロールバックすることができます。それが私のアプローチです。

+0

より普遍的です容疑者。 – Erich

3

これは、より高速なChangeTypeの私のバージョンです。私は原則は@CraigTPで提案されているのと同じだと思うが、null値の型に対してのみ動作する。

私は、値の型がターゲットの型と互換性がある可能性が高いという事実に私の変換メソッドを基にしています。しかし、この方法はパフォーマンスのために設計されておらず、便利に設計されていました。これはタイトなループの中から私が呼びたいものではありません。

私はまだChangeTypeに戻っていますが、できるだけ早期にオプトアウトするようにしています。

public static T? ToOrDefault<T>(object value) 
    where T : struct, IConvertible 
{ 
    var x = value as T?; 
    if (x.HasValue) 
    { 
     return x; 
    } 
    if (value == null || Convert.IsDBNull(value)) 
    { 
     return null; 
    } 
    try 
    { 
     return (T)Convert.ChangeType(value, typeof(T), CultureInfo.InvariantCulture); 
    } 
    catch (InvalidCastException) 
    { 
    } 
    catch (FormatException) 
    { 
    } 
    catch (OverflowException) 
    { 
    } 
    catch (ArgumentException) 
    { 
    } 
    return default(T?); 
} 
+0

あなたのコードで上記のコードをどのように使用するのかを教えてください。 – Naomi

+0

さて、 'DataTable'クラスを考えてみましょう。どこかに値があれば、それらはすべて' object''として公開されています。そこに数字があるとしましょう。 DataTableテーブル。 int? num = ToOrDefault (table.Rows [0] [3]); '数値を取得する方法があれば成功し、それ以外の場合はnullを返します。例外をスローしないでください! –

+0

あなたのコードのcatch'em'all部分は私に恐怖と恐怖を与えます。何かが間違っている場合(例外)、エラーを無視するとデータの整合性の問題が生じる可能性があります。 – SandRock

0

これより高速ではテストしていませんが、これは動的キャストの代替方法です。あなたが見てきたようConvert.ChangeType()は、いくつかの制限がありますので、これは問題は私の仕事ではないだろう、ソースが文字列ではなく、実際の値であるということですので、キャスティング(GUIDは、Null許容型の)、ALSP

value = (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(str);