代码之家  ›  专栏  ›  技术社区  ›  MatthewMartin muthu

如何让泛型处理需要仔细转换的返回值?

  •  7
  • MatthewMartin muthu  · 技术社区  · 14 年前

    我有一些数据访问层代码调用存储过程并返回各种数据类型的标量值。语法是executedecimal、executestring等。我希望它是 Execute<string> Execute<decimal>

    我尝试这个实现,但我无法编译,除非我使用“(T)值进行强制转换”,如果我尝试检查类型并调用一个方法来进行强制转换,就没有这样的运气了。

    更新的问题 为什么在转换为T之前必须转换为对象?

    更新代码

    internal T Execute<T>(string storedProcName, Hashtable parameters)
    {
          //Next lines do compile (thanks to suggestions from answers!)
          if (typeof(T) == typeof(string))
              return (T) (object) ExecuteScalar(storedProcName, parameters).ToString();
          else if (typeof(T) == typeof(int))
              return (T)(object) Convert.ToInt32(ExecuteScalar(storedProcName, parameters));
          //Next line compiles, but not all things boxed in an object can
          //be converted straight to type T (esp db return values that might contain DbNull.Value, etc)
          return (T)ExecuteScalar(storedProcName, parameters);
    }
    
    4 回复  |  直到 7 年前
        1
  •  11
  •   JohnLBevan    7 年前

    试试这个:

    var result = ExecuteScalar(storedProcName, parameters);
    if(Convert.IsDBNull(result))
        return default(T);
    if(result is T) // just unbox
        return (T)result;
    else            // convert
        return (T)Convert.ChangeType(result, typeof(T));
    

    更新的 :固定dbnull处理

        2
  •  1
  •   Andrey    14 年前
    typeof(T) == typeof(string)
    

    对于空值,请检查 DBNull.Value

    整体方法:

    internal T Execute<T>(string storedProcName, Hashtable parameters)
    {
          object res = ExecuteScalar(storedProcName, parameters);
          if (Convert.IsDBNull(res))
             return default(T); //or handle somehow
          return (T)Convert.ChangeType(res, typeof(T));
    }
    
        3
  •  1
  •   paquetp    14 年前

    尝试“as”关键字

    object o = ExecuteScalar(storedProcName, parameters);
    string s;
    int i;
    // .. more
    
    if ((s = o as string) != null)
    {
      return s;
    }
    if ((i = o as int?) != null) // can't use as for value types, so use nullable
    {
      return Convert.ToInt32(o);
    }
    return o as T;
    
        4
  •  0
  •   Reddog    14 年前

    也许您的函数会被修改为允许传入对象转换函数:

    internal T Execute<T>(string storedProcName, Hashtable parameters, Func<object, T> resultConverter)
    {
    }
    

    然后,您可以为您知道的内容创建重载:

    internal string ExecuteForString(string storedProcName, Hashtable parameters)
    {
        return Execute(storedProcName, parameters, (o) => o.ToString());
    }
    
    internal int ExecuteForInt(string storedProcName, Hashtable parameters)
    {
         return Execute(storedProcName, parameters, Convert.ToInt32);
    }
    

    对于dbnull检查,您可以返回 default(T) 或者,如果返回dbnull,可以添加另一个重载来传入默认值-例如,对于int,最好返回-1而不是0。