変換するタイプの既知のセットがある場合は、一連のif/elseif/elseif/else
(またはswitch/case
タイプ名に対して) を実行して、本質的にそれを特殊な解析メソッドに配布できます。これはかなり速いはずです。これは、@ Fabio's answerで説明されているとおりです。
それでもパフォーマンスの問題がある場合は、サポートする必要がある新しい解析メソッドを追加できるルックアップ テーブルを作成することもできます。
いくつかの基本的な解析ラッパーが与えられた場合:
public delegate bool TryParseMethod<T>(string input, out T value);
public interface ITryParser
{
bool TryParse(string input, out object value);
}
public class TryParser<T> : ITryParser
{
private TryParseMethod<T> ParsingMethod;
public TryParser(TryParseMethod<T> parsingMethod)
{
this.ParsingMethod = parsingMethod;
}
public bool TryParse(string input, out object value)
{
T parsedOutput;
bool success = ParsingMethod(input, out parsedOutput);
value = parsedOutput;
return success;
}
}
次に、ルックアップを実行して適切なパーサーを呼び出す変換ヘルパーをセットアップできます。
public static class DataConversion
{
private static Dictionary<Type, ITryParser> Parsers;
static DataConversion()
{
Parsers = new Dictionary<Type, ITryParser>();
AddParser<DateTime>(DateTime.TryParse);
AddParser<int>(Int32.TryParse);
AddParser<double>(Double.TryParse);
AddParser<decimal>(Decimal.TryParse);
AddParser<string>((string input, out string value) => {value = input; return true;});
}
public static void AddParser<T>(TryParseMethod<T> parseMethod)
{
Parsers.Add(typeof(T), new TryParser<T>(parseMethod));
}
public static bool Convert<T>(string input, out T value)
{
object parseResult;
bool success = Convert(typeof(T), input, out parseResult);
if (success)
value = (T)parseResult;
else
value = default(T);
return success;
}
public static bool Convert(Type type, string input, out object value)
{
ITryParser parser;
if (Parsers.TryGetValue(type, out parser))
return parser.TryParse(input, out value);
else
throw new NotSupportedException(String.Format("The specified type \"{0}\" is not supported.", type.FullName));
}
}
次に、使用法は次のようになります。
//for a known type at compile time
int value;
if (!DataConversion.Convert<int>("3", out value))
{
//log failure
}
//or for unknown type at compile time:
object value;
if (!DataConversion.Convert(myType, dataValue, out value))
{
//log failure
}
これにより、おそらくジェネリックが拡張されて、object
ボクシングと型キャストが回避される可能性がありますが、現状ではこれで問題なく動作します。おそらく、測定可能なパフォーマンスがある場合にのみ、その側面を最適化してください。
編集:DataConversion.Convert
指定されたコンバーターが登録されていない場合は、メソッドにフォールバックするTypeConverter
か、適切な例外をスローできるように、メソッドを更新できます。キャッチオールを使用するか、定義済みのサポートされているタイプのセットを使用して、最初からtry/catch
やり直すことを避けるかは、あなた次第です。NotSupportedException
現状では、サポートされていない型を示すメッセージとともにをスローするようにコードが更新されています。意味があるので自由に微調整してください。パフォーマンスに関しては、最も一般的に使用される型に特化したパーサーを指定すると、キャッチオールを実行することが理にかなっている可能性があります。