将对象投射到 T
Posted
技术标签:
【中文标题】将对象投射到 T【英文标题】:Cast object to T 【发布时间】:2009-05-22 19:38:04 【问题描述】:我正在使用 .NET 中的 XmlReader
类解析 XML 文件,我认为编写一个通用解析函数来通用读取不同属性会很聪明。我想出了以下功能:
private static T ReadData<T>(XmlReader reader, string value)
reader.MoveToAttribute(value);
object readData = reader.ReadContentAsObject();
return (T)readData;
我开始意识到,这并没有完全按照我的计划进行;它会抛出诸如int
或double
等基本类型的错误,因为强制转换无法从string
转换为数字类型。有没有办法让我的功能以修改后的形式占上风?
【问题讨论】:
【参考方案1】:先看看能不能施放。
if (readData is T)
return (T)readData;
try
return (T)Convert.ChangeType(readData, typeof(T));
catch (InvalidCastException)
return default(T);
【讨论】:
我将 Convert.ChangeType 的行更改为:'return (T)Convert.ChangeType(readData, typeof(T), System.Globalization.CultureInfo.InstalledUICulture.NumberFormat) 使其适用于各种不同的文化结构。 这是正确答案。但我可以说 try/catch 在这里完全是多余的。特别是考虑到静音异常。我认为 if(readData is T) ... 部分是一个足够的尝试。 您可以在转换之前检查 readDate 是否为空。如果是,则返回默认值(T)。 我得到“对象必须实现 IConvertible。”【参考方案2】:你试过Convert.ChangeType吗?
如果该方法总是返回一个字符串,我觉得这很奇怪,但这不是重点,那么这个更改后的代码可能会满足您的需求:
private static T ReadData<T>(XmlReader reader, string value)
reader.MoveToAttribute(value);
object readData = reader.ReadContentAsObject();
return (T)Convert.ChangeType(readData, typeof(T));
【讨论】:
我最初确实查看了 Convert.ChangeType,但由于某些奇怪的原因,我认为它对这个操作没有用。您和 Bob 都提供了相同的答案,我决定混合使用您的答案,因此我避免使用 try 语句,但仍尽可能使用“return (T)readData”。【参考方案3】:试试
if (readData is T)
return (T)(object)readData;
【讨论】:
【参考方案4】:您可以要求类型是引用类型:
private static T ReadData<T>(XmlReader reader, string value) where T : class
reader.MoveToAttribute(value);
object readData = reader.ReadContentAsObject();
return (T)readData;
然后做另一个使用值类型和 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
//...
【讨论】:
【参考方案5】:其实这里的问题是ReadContentAsObject的使用。不幸的是,这种方法没有达到预期。虽然它应该检测该值的最合适类型,但它实际上返回一个字符串,无论如何(这可以使用 Reflector 进行验证)。
但是,在您的具体情况下,您已经知道要转换为的类型,因此我会说您使用了错误的方法。
尝试改用 ReadContentAs,这正是您所需要的。
private static T ReadData<T>(XmlReader reader, string value)
reader.MoveToAttribute(value);
object readData = reader.ReadContentAs(typeof(T), null);
return (T)readData;
【讨论】:
看起来相当紧凑和优雅。但是,已接受答案中的解决方案使用了与多种不同文化兼容的 ChangeType,因为它接受 IFormatProvider。由于这是该项目的必需品,因此我将继续使用该解决方案。【参考方案6】:添加“类”约束(或更详细,如预期 T 对象的基类或接口):
private static T ReadData<T>(XmlReader reader, string value) where T : class
reader.MoveToAttribute(value);
object readData = reader.ReadContentAsObject();
return (T)readData;
或where T : IMyInterface
或where T : new()
等
【讨论】:
【参考方案7】:您大概可以作为参数传入一个委托,该委托将从字符串转换为 T。
【讨论】:
【参考方案8】:实际上,响应提出了一个有趣的问题,即您希望函数在出现错误时执行的操作。
也许以 TryParse 方法的形式构造它会更有意义,该方法尝试读入 T,但如果无法完成则返回 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;
编辑:现在我考虑一下,我真的需要进行 convert.changetype 测试吗? as 行不是已经尝试这样做了吗?我不确定做那个额外的 changetype 调用是否真的能完成任何事情。实际上,它可能只是通过生成异常来增加处理开销。如果有人知道值得做的不同之处,请发布!
【讨论】:
以上是关于将对象投射到 T的主要内容,如果未能解决你的问题,请参考以下文章