显式Int转换溢出

本文关键字:溢出 转换 Int 显式 | 更新日期: 2023-09-27 18:27:48

问题

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

背景

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

步骤1

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

步骤2

然后我使用代码将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; }
}

步骤3

我使用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();
    }
}

步骤4

然后在客户端应用程序中,我从服务引用中检索它,默认绑定为WSHttpBinding,代码为:

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说:

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

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

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

请帮忙,提前谢谢。

显式Int转换溢出

这里发生了一些可疑的事情。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));
}

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

  • 右键单击项目,然后单击属性
  • 单击构建选项卡
  • 单击高级…按钮
  • 选中"检查算术上溢/下溢"复选框

如果选中或未选中,我不知道你能在哪里找到。但这取决于您的编译器选项,如中所述http://msdn.microsoft.com/en-us/library/khy08726(v=vs.100).aspx

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

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

  • Int32
  • Uint32
  • Int64(长)
  • Uint64(ulong)

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

[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不会。