显式Int转换溢出

时间:2012-03-15 10:05:46

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

问题

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

背景

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

第1步

在我的 WCF服务中,我使用DataTable

检索IBM.Data.DB2.iSeries.iDB2DataAdapter.Fill(DataSet)

第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 says

  

当您从 double float 值转换为整数类型时,该值将被截断。如果结果积分值超出目标值的范围,则结果取决于溢出检查上下文。在已检查的上下文中,抛出了OverflowException,而在未经检查的上下文中,结果是未指定的目标类型值。

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

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

请提前帮助,谢谢。

4 个答案:

答案 0 :(得分:2)

这里有一些可疑的东西。 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));
}

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

如果您选中或取消选中,我不确切知道您在哪里可以找到。但这取决于http://msdn.microsoft.com/en-us/library/khy08726(v=vs.100).aspx

中所述的编译器选项

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

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

答案 3 :(得分:0)

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

[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?< / p>

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