У меня есть следующий сценарий, где я хочу передать строку и общий тип:
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()
является проблемой) или если есть лучшее решение, которое я не рассматривал.