【问题标题】:Explicit Int Conversion Overflow显式 Int 转换溢出
【发布时间】:2012-03-15 10:05:45
【问题描述】:

问题

当我将值传递给int 变量时,如果该值超过int 的最大值,int 变量的值将变为0

背景

我使用以下步骤来检索我的数据。我不使用任何 try-catch 块而不抛出异常。

步骤 1

在我的WCF 服务 中,我使用IBM.Data.DB2.iSeries.iDB2DataAdapter.Fill(DataSet) 检索DataTable

第二步

然后我使用代码将DataTable 转换为List<T>

public static List<T> DataTableToList<T>(DataTable dt)
{
    List<T> tableEntity = new List<T>();

    foreach (DataRow row in dt.Rows)
    {
        T rowEntity = Activator.CreateInstance<T>();

        rowEntity.GetType().GetProperties().Where(o => dt.Columns.OfType<DataColumn>()
            .Select(p => p.ColumnName).Contains(o.Name)).ToList()
            .ForEach(o => o.SetValue(rowEntity, row[o.Name], null));

        tableEntity.Add(rowEntity);
    }

    return tableEntity;
}

类型:

public class Client
{
    public int ID { get; set; }
    public string Name { get; set; }
}

第三步

我使用 WCF 服务方法返回它:

[OperationContract]
public string GetClients()
{
    List<Client> clients = new DB().RetrieveClients();
    return Tools.SerializeObjectToXML<List<Client>>(clients);
}

使用辅助方法进行序列化:

public static string SerializeObjectToXML<T>(T item)
{
    XmlSerializer xs = new XmlSerializer(typeof(T));
    using (StringWriter writer = new StringWriter())
    {
        xs.Serialize(writer, item);
        return writer.ToString();
    }
}

第四步

然后在 Client Application 中,我使用 WSHttpBinding 的默认绑定从 Service Reference 中检索它,代码如下:

List<Client> clients = Tools.DeserializeXMLToObject<List<Client>>(new SomeServiceClient().GetClients());

使用反序列化的辅助方法:

public static T DeserializeXMLToObject<T>(string xmlText)
{
    if (string.IsNullOrEmpty(xmlText)) return default(T);
    XmlSerializer xs = new XmlSerializer(typeof(T));
    using (MemoryStream memoryStream = new MemoryStream(new UnicodeEncoding().GetBytes(xmlText)))
    using (XmlTextReader xsText = new XmlTextReader(memoryStream))
    {
        xsText.Normalization = true;
        return (T)xs.Deserialize(xsText);
    }
}

问题

msdn says 那个:

当您从 doublefloat 值转换为整数类型时,该值将被截断。如果生成的整数值超出目标值的范围,则结果取决于溢出检查上下文。在已检查的上下文中,会引发 OverflowException,而在未检查的上下文中,结果是目标类型的未指定值。

  • 当数据库中的值超过 int 允许的最大值时,为什么 Client.ID 的值会变为 0
  • 是因为它是未经检查的上下文吗?如果是,我怎么知道?

我的代码是 C#,框架 4,在 VS2010 Pro 中构建。

请帮忙,提前谢谢。

【问题讨论】:

  • 那里有很多代码,你能澄清一下这个意外转换到底发生在哪里以及输入和输出是什么?在这样的问题中,最好尝试创建一个最小的测试用例。目前我不能轻易地使用上面的方法来重现你的问题,这让我不太愿意帮助回答它。您甚至没有解释哪里出了问题(我假设您已经调试到足以知道发生意外行为的位置)。如果您知道数据库正在传递大值,那么作为最后一条评论,为什么将它们放在不适合的数据类型中?
  • 另外你确定你没有截断数据库代码中的值吗?查看您的代码后,我假设 DataTableToList 方法正在写入您的 ID,但如果它试图将 Int64 或双精度写入 Int32 字段,我希望这会失败,所以您确定数据表中的内容肯定会超过 int.Max?

标签: c# wcf .net-4.0 type-conversion


【解决方案1】:

这里发生了一些可疑的事情。 SetValue 不进行强制转换/转换(甚至从 uintint 都没有,刚刚测试过)。您最好将ForEach 代码放大为真正的foreach 并对其进行调试。

例如:

foreach (var o in rowEntity.GetType().GetProperties().Where(o => dt.Columns.OfType<DataColumn>()
        .Select(p => p.ColumnName).Contains(o.Name)))
{
    if (o.Name == "ID")
    {
        // Put a breakpoint here
    }

    o.SetValue(rowEntity, row[o.Name], null));
}

【讨论】:

  • 是的,我正在查看它并怀疑有一个存储过程实际上负责某处的截断......
【解决方案2】:

默认情况下,算术溢出编译器开关在 Visual Studio 中处于关闭状态。要启用它:

  • 右键单击项目,然后单击属性
  • 点击构建标签。
  • 点击高级...按钮。
  • 选中检查算术上溢/下溢复选框。

【讨论】:

    【解决方案3】:

    我不知道你在哪里可以找到你是否选中。但这取决于http://msdn.microsoft.com/en-us/library/khy08726(v=vs.100).aspx中所述的编译器选项@

    正如 Thorsten Dittmar 所说,您可以更好地使用 DataContract 轻松发送客户端。

    如果它溢出,您可以更好地使用long 作为id 而不是int。这样它就有更多的职位(long == Int64)。如果您的所有 Id 都 > 0,您可以使用 unsigned int 或 unsigned long 作为您的 Id。无符号表示,它的数字不是低于零,而是只有正数,因此是正数的两倍。

    【讨论】:

      【解决方案4】:

      只是一个问题:为什么将列表作为字符串传输而不是执行以下操作:

      [OperationContract]
      public Client[] GetClients()
      {
          List<Client> clients = new DB().RetrieveClients();
          return clients.ToArray();
      }
      

      并声明Client 类,如:

      [DataContract]
      public class Client
      {
          [DataMember]
          public int ID;
      
          [DataMember]
          public string Name;
      }
      

      另外:如果数据库中ID 的类型允许大于Int32.MaxValue 的值,为什么要使用Int32 而不是Int64

      关于溢出检查:我知道使用Convert.ToInt32(Int64.MaxValue); 会引发异常,而int i = (int)Int64.MaxValue 不会。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多