C# 我该如何解决这个问题以将通用转换为 Nullable<T>?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/793714/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I fix this up to do generic conversion to Nullable<T>?
提问by TheSoftwareJedi
I currently use this handy conversion extension method to do conversions between types:
我目前使用这个方便的转换扩展方来进行类型之间的转换:
public static T To<T>(this IConvertible obj)
{
return (T)Convert.ChangeType(obj, typeof(T));
}
However, it doesn't like converting valid values to Nullable, for example, this fails:
但是,它不喜欢将有效值转换为 Nullable,例如,这会失败:
"1".To<int?>();
Obviously, 1 is easily converted to an (int?), but it gets the error:
显然,1 很容易转换为 (int?),但它会得到错误:
Invalid cast from 'System.String' to 'System.Nullable`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'.
This is an obviously simplified example, in reality I'm using it to do conversions from string types like so:
这是一个明显简化的示例,实际上我使用它来进行字符串类型的转换,如下所示:
packageDb.Quantity = package.package.ElementDeep(Namespace + "PackageQuantity", Namespace + "ActualQuantity", Namespace + "Quantity").ValueOrNull().To<int?>();
If Convert.ChangeType doesn't like Nullable, anyone have any great ideas?
如果 Convert.ChangeType 不喜欢 Nullable,有人有什么好主意吗?
采纳答案by LukeH
public static T To<T>(this IConvertible obj)
{
Type t = typeof(T);
Type u = Nullable.GetUnderlyingType(t);
if (u != null)
{
return (obj == null) ? default(T) : (T)Convert.ChangeType(obj, u);
}
else
{
return (T)Convert.ChangeType(obj, t);
}
}
回答by Adam Robinson
Maybe I'm missing the point, but in the instance of Nullable, how does your method provide either a readability, performance, or maintenance advantage over a simple cast, like (int?)1
?
也许我没有抓住重点,但是在 Nullable 的实例中,与简单的强制转换相比,您的方如何提供可读性、性能或维护优势,例如(int?)1
?
Aside from that, perhaps another extension method?
除此之外,也许是另一种扩展方?
public static T? ToNullable<T>(this T obj) where T:struct
{
return (T?)obj;
}
Edit
编辑
After reviewing your edit, why would the generic function that I provided not work as a substitute to your To<T>
function in that line of code? You can't allow a conversion to Nullable for any type (which is why ChangeType
doesn't work) because that generic only accepts value types. You'll either have to use a function like the one I provided or change your signature of To<T>
to only accept value types and add a special case for Nullable<T>
.
在查看您的编辑后,为什么我提供的通用函数不能To<T>
在该行代码中替代您的函数?您不能允许任何类型转换为 Nullable(这就是为什么ChangeType
不起作用),因为该泛型只接受值类型。您要么必须使用我提供的函数,要么将您的签名更改To<T>
为仅接受值类型并为Nullable<T>
.
回答by Nathan Koop
This is the method that I currently use (I got my answer on SO), it converts from string to nullable type:
这是我目前使用的方(我在SO上得到了答案),它从字符串转换为可空类型:
public static Nullable<T> ConvertToNullable<T>(this string s) where T : struct
{
if (!string.IsNullOrEmpty(s.Trim()))
{
TypeConverter conv = TypeDescriptor.GetConverter(typeof(Nullable<>).MakeGenericType(typeof(T)));
return (Nullable<T>)conv.ConvertFrom(s);
}
return null;
}
回答by Henrique
public static T To<T>(this IConvertible obj)
{
Type t = typeof(T);
if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>))
t = t.GetGenericArguments()[0];
return (T)Convert.ChangeType(obj, t);
}
But if the conversion fail, it will throw an exception, not returning a null as should be expected.
但是如果转换失败,它将抛出异常,而不是像预期的那样返回 null。
回答by Eugenio Miró
Luke's solution was good for me (and obviously got his up vote) but I simplified it for me this way
卢克的解决方案对我有好处(显然得到了他的支持),但我以这种方式为我简化了它
private static Type ResolveType(String typeName)
{
Type t = Type.GetType(typeName);
if (t == null)
return null;
Type u = Nullable.GetUnderlyingType(t);
if (u != null) {
t = u;
}
return t;
}
because I started from a string not from a type... thoughts?
因为我从一个字符串而不是一个类型开始......想?
回答by Nick Strupat
I've ended up with this
我已经结束了这个
private static T To<T>(this Object @object, Boolean returnDefaultOnException)
{
Type type = typeof(T);
Type underlyingTypeOfNullable = Nullable.GetUnderlyingType(type);
try
{
return (T) Convert.ChangeType(@object, underlyingTypeOfNullable ?? type);
}
catch (Exception exception)
{
if (returnDefaultOnException)
return default(T);
String typeName = type.Name;
if (underlyingTypeOfNullable != null)
typeName += " of " + underlyingTypeOfNullable.Name;
throw new InvalidCastException("Object can't be cast to " + typeName, exception);
}
}
public static T To<T>(this Object @object) { return @object.To<T>(returnDefaultOnException: false); }
public static T ToOrDefault<T>(this Object @object) { return @object.To<T>(returnDefaultOnException: true); }
It behaves like the LINQ extension methods Single
and SingleOrDefault
and First
and FirstOrDefault
.
它的行为像LINQ扩展方Single
和SingleOrDefault
和First
和FirstOrDefault
。
In short, To<T>()
tries to convert and throws on failure while ToOrDefault<T>()
tries to convert and returns default(T)
on failure.
简而言之,To<T>()
尝试转换并在失败时抛出,而ToOrDefault<T>()
尝试转换并default(T)
在失败时返回。
回答by Hossein Shahabi
extend @LukeH code:
扩展@LukeH 代码:
public static T GetValue<T>(string Literal, T DefaultValue)
{
if (Literal == null || Literal == "" || Literal == string.Empty) return DefaultValue;
IConvertible obj = Literal;
Type t = typeof(T);
Type u = Nullable.GetUnderlyingType(t);
if (u != null)
{
return (obj == null) ? DefaultValue : (T)Convert.ChangeType(obj, u);
}
else
{
return (T)Convert.ChangeType(obj, t);
}
}
回答by Pangamma
This method does what you need, and it looks nice while doing it.
这种方可以满足您的需求,并且在执行时看起来不错。
/// <summary>
/// <para>More convenient than using T.TryParse(string, out T).
/// Works with primitive types, structs, and enums.
/// Tries to parse the string to an instance of the type specified.
/// If the input cannot be parsed, null will be returned.
/// </para>
/// <para>
/// If the value of the caller is null, null will be returned.
/// So if you have "string s = null;" and then you try "s.ToNullable...",
/// null will be returned. No null exception will be thrown.
/// </para>
/// <author>Contributed by Taylor Love (Pangamma)</author>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="p_self"></param>
/// <returns></returns>
public static T? ToNullable<T>(this string p_self) where T : struct
{
if (!string.IsNullOrEmpty(p_self))
{
var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(T));
if (converter.IsValid(p_self)) return (T)converter.ConvertFromString(p_self);
if (typeof(T).IsEnum) { T t; if (Enum.TryParse<T>(p_self, out t)) return t;}
}
return null;
}
https://github.com/Pangamma/PangammaUtilities-CSharp/tree/master/src/StringExtensions
https://github.com/Pangamma/PangammaUtilities-CSharp/tree/master/src/StringExtensions