Тип возвращаемого значения общего типа в качестве параметра типа
У меня есть метод расширения, который работает нормально, чтобы отличать строковые значения в разных типах, что выглядит примерно так:
public static T ToType<T> (this string value, T property)
{
object parsedValue = default(T);
Type type = property.GetType();
try
{
parsedValue = Convert.ChangeType(value, type);
}
catch (ArgumentException e)
{
parsedValue = null;
}
return (T)parsedValue;
}
Я недоволен тем, как это выглядит при вызове метода:
myObject.someProperty = stringData.ToType(myObject.someProperty);
Указание свойства только для получения типа свойства кажется излишним. Я бы предпочел использовать такую подпись:
public static T ToType<T> (this string value, Type type) { ... }
а T - тип типа. Это сделает звонки намного чище:
myObject.someProperty = stringData.ToType(typeof(decimal));
Однако, когда я пытаюсь позвонить таким образом, редактор жалуется, что возвращаемый тип метода расширения не может быть выведен из использования. Могу ли я связать T с аргументом Type?
Что мне не хватает?
Спасибо
Ответы
Ответ 1
Это то, что вы ищете? Я добавил дополнительный улов для случаев, когда акты недействительны также
Decimal i = stringName.ToType<Decimal>();
public static T ToType<T>(this string value)
{
object parsedValue = default(T);
try
{
parsedValue = Convert.ChangeType(value, typeof(T));
}
catch (InvalidCastException)
{
parsedValue = null;
}
catch (ArgumentException)
{
parsedValue = null;
}
return (T)parsedValue;
}
Edit
контекстный подход для исправления комментария Антона
if (typeof(T).IsValueType)
return default(T);
Ответ 2
Зачем использовать свойство вообще? Просто измените, как вы устанавливаете переменную типа в тип своего общего.
public static T ToType<T>(this string value)
{
object parsedValue = default(T);
Type type = typeof(T);
try
{
parsedValue = Convert.ChangeType(value, type);
}
catch (ArgumentException e)
{
parsedValue = null;
}
return (T) parsedValue;
}
Использование:
myObject.someProperty = stringData.ToType<decimal>()
Ответ 3
Я использую это для общего преобразования:
public bool ConvertTo<T>(object from, out T to) {
to = default(T);
if (from is T) { to = (T)from; return true; }
Type t = typeof(T);
//TypeConverter converter = p.converter == null ? TypeDescriptor.GetConverter(t) : p.converter;
TypeConverter converter = TypeDescriptor.GetConverter(t);
if ((converter != null) && (converter.CanConvertTo(t))) {
try { to = (T)converter.ConvertTo(null, culture, from, t); return true; }
catch { }
}
try { to = (T)Convert.ChangeType(from, t, culture); return true; }
catch { }
return false;
}
public bool ConvertTo(object from, out object to, Type type) {
to = null;
if (from.GetType() == type) { to = from; return true; }
TypeConverter converter = TypeDescriptor.GetConverter(type);
if ((converter != null) && (converter.CanConvertTo(type))) {
try { to = converter.ConvertTo(null, culture, from, type); return true; }
catch { }
}
try { to = Convert.ChangeType(from, type, culture); return true; }
catch { }
return false;
}
Перед вызовом Convert.ChangeType
это проверяет наличие TypeConverter
для данной переменной.
Назовите его так:
int i = 123;
string s;
if (ConvertTo<string>(i, out s) {
// use s
}