C# 将对象投射到 T
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/899629/
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
Cast object to T
提问by Kasper Holdum
I'm parsing an XML file with the XmlReader
class in .NET and I thought it would be smart to write a generic parse function to read different attributes generically. I came up with the following function:
我正在用XmlReader
.NET 中的类解析 XML 文件,我认为编写一个通用的解析函数来通用地读取不同的属性会很聪明。我想出了以下功能:
private static T ReadData<T>(XmlReader reader, string value)
{
reader.MoveToAttribute(value);
object readData = reader.ReadContentAsObject();
return (T)readData;
}
As I came to realise, this does not work entirely as I have planned; it throws an error with primitive types such as int
or double
, since a cast cannot convert from a string
to a numeric type. Is there any way for my function to prevail in modified form?
我逐渐意识到,这并不完全按照我的计划进行。它会在原始类型(例如int
or )中引发错误double
,因为强制转换无法从 a 转换string
为数字类型。有什么办法可以让我的函数以修改后的形式占上风?
采纳答案by Bob
First check to see if it can be cast.
首先检查是否可以投射。
if (readData is T) {
return (T)readData;
}
try {
return (T)Convert.ChangeType(readData, typeof(T));
}
catch (InvalidCastException) {
return default(T);
}
回答by Lasse V. Karlsen
Have you tried Convert.ChangeType?
你试过Convert.ChangeType吗?
If the method always returns a string, which I find odd, but that's besides the point, then perhaps this changed code would do what you want:
如果该方法总是返回一个字符串,我觉得这很奇怪,但这不是重点,那么这个更改后的代码可能会做你想要的:
private static T ReadData<T>(XmlReader reader, string value)
{
reader.MoveToAttribute(value);
object readData = reader.ReadContentAsObject();
return (T)Convert.ChangeType(readData, typeof(T));
}
回答by Ricardo Villamil
Add a 'class' constraint (or more detailed, like a base class or interface of your exepected T objects):
添加“类”约束(或更详细的,如您期望的 T 对象的基类或接口):
private static T ReadData<T>(XmlReader reader, string value) where T : class
{
reader.MoveToAttribute(value);
object readData = reader.ReadContentAsObject();
return (T)readData;
}
or where T : IMyInterface
or where T : new()
, etc
或where T : IMyInterface
或where T : new()
等
回答by ChrisW
You can presumably pass-in, as a parameter, a delegate which will convert from string to T.
您大概可以作为参数传入一个委托,该委托将从字符串转换为 T。
回答by Tom Ritter
You could require the type to be a reference type :
您可以要求类型为引用类型:
private static T ReadData<T>(XmlReader reader, string value) where T : class
{
reader.MoveToAttribute(value);
object readData = reader.ReadContentAsObject();
return (T)readData;
}
And then do another that uses value types and TryParse...
然后再做一个使用值类型和 TryParse 的...
private static T ReadDataV<T>(XmlReader reader, string value) where T : struct
{
reader.MoveToAttribute(value);
object readData = reader.ReadContentAsObject();
int outInt;
if(int.TryParse(readData, out outInt))
return outInt
//...
}
回答by Sadegh
try
尝试
if (readData is T)
return (T)(object)readData;
回答by genki
Actually, the responses bring up an interesting question, which is what you want your function to do in the case of error.
实际上,这些响应提出了一个有趣的问题,即您希望函数在出现错误时执行的操作。
Maybe it would make more sense to construct it in the form of a TryParse method that attempts to read into T, but returns false if it can't be done?
也许以尝试读入 T 的 TryParse 方法的形式构造它会更有意义,但如果无法完成则返回 false?
private static bool ReadData<T>(XmlReader reader, string value, out T data)
{
bool result = false;
try
{
reader.MoveToAttribute(value);
object readData = reader.ReadContentAsObject();
data = readData as T;
if (data == null)
{
// see if we can convert to the requested type
data = (T)Convert.ChangeType(readData, typeof(T));
}
result = (data != null);
}
catch (InvalidCastException) { }
catch (Exception ex)
{
// add in any other exception handling here, invalid xml or whatnot
}
// make sure data is set to a default value
data = (result) ? data : default(T);
return result;
}
edit: now that I think about it, do I really need to do the convert.changetype test? doesn't the as line already try to do that? I'm not sure that doing that additional changetype call actually accomplishes anything. Actually, it might just increase the processing overhead by generating exception. If anyone knows of a difference that makes it worth doing, please post!
编辑:现在我想想,我真的需要做 convert.changetype 测试吗?as 行不是已经尝试这样做了吗?我不确定执行那个额外的 changetype 调用是否真的能完成任何事情。实际上,它可能只是通过生成异常来增加处理开销。如果有人知道值得做的差异,请发布!
回答by baretta
Actually, the problem here is the use of ReadContentAsObject. Unfortunately, this method does not live up to its expectations; while it should detect the most appropirate type for the value, it actually returns a string, no matter what(this can be verified using Reflector).
实际上,这里的问题是 ReadContentAsObject 的使用。不幸的是,这种方法没有达到预期;虽然它应该检测最合适的值类型,但它实际上返回一个字符串,无论如何(这可以使用反射器进行验证)。
However, in your specific case, you already know the type you want to cast to, therefore i would say you are using the wrong method.
但是,在您的特定情况下,您已经知道要强制转换的类型,因此我会说您使用了错误的方法。
Try using ReadContentAs instead, it's exactly what you need.
尝试改用 ReadContentAs,这正是您所需要的。
private static T ReadData<T>(XmlReader reader, string value)
{
reader.MoveToAttribute(value);
object readData = reader.ReadContentAs(typeof(T), null);
return (T)readData;
}