У меня есть следующий сценарий, где я хочу передать строку и общий тип:
public class Worker {
public void DoSomeWork<T>(string value)
where T : struct, IComparable<T>, IEquatable<T> { ... }
}
В какой-то момент по пути мне нужно преобразовать значение строки в значение T. Но я не хочу делать прямой конвертировать, поскольку мне нужно выполнить некоторую логику, если строка не может быть преобразована в тип T.
Я думал, что могу попробовать использовать Convert.ChangeType(), но у этой проблемы есть проблема, что если она не будет конвертироваться, это вызовет исключение, и я буду использовать метод DoSomeWork() достаточно часто, чтобы не полагаться на try/catch, чтобы определить, действительно ли преобразован.
Итак, это заставило меня задуматься, я знаю, что буду работать с числовыми типами, следовательно, T будет любым из следующих: int, uint, short, ushort, long, ulong, byte, sbyte, decimal, float, double. Зная это, я подумал, что можно было бы найти более быстрое решение, работающее с тем, что я знаю, что буду использовать числовые типы (обратите внимание, если T не является числовым типом, я выдаю исключение)...
public class NumericWorker {
public void DoSomeWork<T>(string value)
where T : struct, IComparable<T>, IEquatable<T>
{
ParseDelegate<T> tryConverter =
SafeConvert.RetreiveNumericTryParseDelegate<T>();
...
}
}
public class SafeConvert
{
public delegate bool ParseDelegate<T>(string value, out T result);
public static ParseDelegate<T> RetreiveNumericTryParseDelegate<T>()
where T : struct, IComparable<T>, IEquatable<T>
{
ParseDelegate<T> tryParseDelegate = null;
if (typeof(T) == typeof(int))
{
tryParseDelegate = (string v, out T t) =>
{
int typedValue;
bool result = int.TryParse(v, out typedValue);
t = result ? (T)typedValue : default(T);
//(T)Convert.ChangeType(typedValue, typeof(T)) : default(T);
return result;
};
}
else if (typeof(T) == typeof(uint)) { ... }
else if (typeof(T) == typeof(short)) { ... }
else if (typeof(T) == typeof(ushort)) { ... }
else if (typeof(T) == typeof(long)) { ... }
else if (typeof(T) == typeof(ulong)) { ... }
else if (typeof(T) == typeof(byte)) { ... }
else if (typeof(T) == typeof(sbyte)) { ... }
else if (typeof(T) == typeof(decimal)) { ... }
else if (typeof(T) == typeof(float)) { ... }
else if (typeof(T) == typeof(double)) { ... }
return tryParseDelegate;
}
}
Но вышеизложенная проблема состоит в том, что я не могу написать t = result ? (T)typedValue : default(T);, поскольку приведение typedValue в T вызывает проблемы и единственный способ, которым я смог обойти это до сих пор, - написать (T)Convert.ChangeType(typedValue, typeof(T)). Но если я это сделаю, я просто делаю другой конверт.
Следовательно, мне было интересно, знает ли кто-нибудь, как я мог бы исправить эту проблему (если вы считаете, что проблема с ChangeType() является проблемой) или если есть лучшее решение, которое я не рассматривал.