0

下面的方法在字典中查找特定的键,如果可以的话,会尝试安全地存储它destination。我遇到的问题是何时T=Int64和字典中的项目是Int32UInt32(两者都可以放入 Int64 而不会丢失数据)。 valueAsObject is T当 T 为 Int64 且 valueAsObject 为 Int32 时返回 false。

是否可以安全地将 valueAsObject 转换为 T 而无需尝试并捕获任何异常?我想避免例外,但如果这是我让它工作的唯一方法。

public static void MyMethod<T>(IDictionary<String, Object> dictionary, String key, ref T destination)
{
    if (!dictionary.ContainsKey(key))
        return;

    var valueAsObject = dictionary[key];
    if (!(valueAsObject is T))
        return;

    destination = (T)valueAsObject;
}

基本上,如果在字典中找到的东西不能安全地存储在类型 T 变量中(没有数据丢失),我希望函数什么都不做(返回),否则它应该根据需要进行转换并存储它。

4

3 回答 3

4

这不是在语言或运行时级别内置的。您可以使用Convert.ChangeType来执行转换。此方法还执行有损转换,因此您可能必须构建自己的转换逻辑(这将涉及强制转换并且很丑陋)。

于 2013-10-03T20:51:07.677 回答
0

你不能就这么干吗?

public static void MyMethod<T>( IDictionary<string,object> dictionary , string key , ref T destination )
{
  object value ;
  bool   found = dictionary.TryGetValue( key , out value ) ;

  if (found && value is T)
  {
    destination = (T) value ;
  }

  return;
}

is运营商:

计算true提供的表达式是否为非空,并且提供的对象可以转换为提供的类型而不会引发异常。

. . .

请注意,is 运算符仅考虑引用转换、装箱转换和拆箱转换。不考虑其他转换,例如用户定义的转换。

基本上,如果对象直接继承自指定类型,或实现该类型(如果T是接口),is则应该返回true并且您应该能够将对象向下转换为您的类型T

但是,如果您需要担心用户定义的转换运算符,则需要对object's 的类型进行反思,typeof(T)以查看是否在将对象转换为兼容的类型上定义了用户定义的转换运算符类型。做到这一点可能是……棘手的。

于 2013-10-03T21:42:43.610 回答
0

这是我采用的最终解决方案。它来自许多评论和其他答案,因此我鼓励阅读其他答案/评论以获取有关为什么需要这样做的更多详细信息:

private static void GetFromDictionary<T>(IDictionary<String, Object> dictionary, String key, ref T outputLocation)
{
    if (!dictionary.ContainsKey(key))
        return;

    var valueAsObject = dictionary[key];
    if (!CanBeCastTo<T>(valueAsObject))
        return;

    outputLocation = (T)Convert.ChangeType(valueAsObject, typeof(T));
}

private static bool CanBeCastTo<T>(Object thingToCast)
{
    if (thingToCast is T)
        return true;

    var tType = typeof(T);
    if (tType == typeof(Int64) && thingToCast is Int32)
        return true;

    if (tType == typeof(Double) && thingToCast is Decimal)
        return true;

    return false;
}

就我而言,我只需要处理原始类型的某个子集(Int32、Int64、String、Double、Decimal),并且我愿意接受 Decimal 到 Double 的有损转换。

这里的要点是“is”运算符将为基元返回 false,即使它可以无损失地拟合(Int64 中的 Int32)。此外,(T)valueAsObject不会进行显式类型转换。因此,如果 valueAsObject 的类型为 Int32 且 T 的类型为 Int64,即使(Int64)valueAsObject有效,上面也会抛出异常。这一点我,但幸运的是@usr 建议使用 Convert.ChangeType 来处理这个问题。

可以对上面的代码进行优化,但为了便于阅读,我选择保留它。

于 2013-10-04T16:22:21.530 回答