有没有试过从一个集合里面移除一个对象之后,这个集合仍然留有这个对象?世界之大,无奇不有。稍有疏忽,便会导致这种奇怪的现象。现在让我们看看这个“不死”对象究竟是怎么一回事。

1、“不死”对象现身

这个问题起初是我一个同事提出的,为了重现“不死”对象,现把代码简化如下:

// Code #01

IList products = new List<Product>();
products.Add(GetProduct("1412"));
products.Remove(GetProduct("1412"));

其中 Product 类代码如下:

// Code #02

class Product
{
    public Product(string id)
    {
        m_ID = id;
    }

    private string m_ID;
    public string ID
    {
        get { return m_ID; }
    }

    public override string ToString()
    {
        return "ID: " + m_ID;
    }
}

而 GetProduct 方法则根据传入的 ID 从数据库读取数据并返回,它的签名如下:

// Code #03

public static Product GetProduct(string id);

要想知道编号为 1412 的对象是否从 products 中移除,只需在 Code #01 的最后加上这样一行:

// Code #04

Console.WriteLine(products.Count);

2、一不小心掉进陷阱

不知道你有没有查看 SDK 的习惯,其实 SDK 里面蕴藏着很多对我们解决问题有启发作用的信息的。现在让我们看看 SDK 里面能否找到什么蛛丝马迹。

由于 products 的真身是 List<T>,所以我们有必要看看 List<T> 是如何实现 IList.Remove 的:

This method determines equality using the default equality comparer EqualityComparer.Default for T, the type of values in the list.

原来,List<T> 在 IList.Remove 中使用 EqualityComparer.Default 来判断两个对象是否相等。那么 EqualityComparer.Default 又是如何得知两个对象是否相等呢?

The Default property checks whether type T implements the System.IEquatable generic interface and if so returns an EqualityComparer that uses that implementation. Otherwise it returns an EqualityComparer that uses the overrides of Object.Equals and Object.GetHashCode provided by T.

把上面这段话结合 Code #02 来看,我们可以发现 List<T> 中的 IList.Remove 判断两个 Product 对象是否相等的方法是从 Object 根类继承下来的 Equals 和 GetHashCode 方法,即比较两个对象的引用是否指向同一个对象。

由于 GetProduct 方法每次返回的都是一个新的对象(暂时让我们忘记对象缓存这家伙),于是就导致了集合里面出现“不死”对象。

3、不要被同一颗子弹打中两次

“不要被同一颗子弹打中两次”原意是指同一个错误不要两次犯,这句话暗含着对两个表示错误的对象进行逻辑上的判等,就像上面需要判断两个 Product 的对象在逻辑上是否相等那样。

至此,我们也知道了令 Remove 重新生效的两个可选办法是:

  • 让 Product 类实现 IEquatable<T> 接口;
  • 为 Product 类重写 Equals 和 GetHashCode 方法。

在大多数情况下,我们希望比较的并不是对象的引用,而是对象的内容,与此同时,我们又不太可能为了这些小对象劳师动众地实现对象缓存,于是,你就很有可能在类似的代码中邂逅“不死”对象了。

 
 
 
4 .例如有一个类

using System;
namespace DB_SecurityMonitor.Model
{
       public partial class m_Sensor
      {
             public m_Sensor()
             {}
             #region Model
            private int _id;
            private string _vc_code;
            private string _vc_memo;
            public int ID
           {
               set{ _id=value;}
               get{return _id;}
           }
           public string vc_Code
           {
                 set{ _vc_code=value;}
                 get{return _vc_code;}
           }
           public string vc_Memo
           {
                 set{ _vc_memo=value;}
                 get{return _vc_memo;}
           }
  #endregion Model

 
        重写Equals,判断当ID相等时就认为是相同的
        public override bool Equals(object obj)
        {
            m_Sensor m = obj as m_Sensor;
            if (this.ID == m.ID)
            {
                return true;
            }
            return false;
        }
}
 
 
            List<DB_SecurityMonitor.Model.m_Sensor> lst = new DB_SecurityMonitor.BLL.m_Sensor().GetModelList("i_flag=0");
            foreach (DB_SecurityMonitor.Model.m_Sensor item in lst)
            {
                lstMonitorSensor.Add(item);
            }
 
           List<DB_SecurityMonitor.Model.m_Sensor> lst = new DB_SecurityMonitor.BLL.m_Sensor().GetModelList("i_flag=0 and ID  in(104,113,99)");
            foreach (DB_SecurityMonitor.Model.m_Sensor item in lst)
            {
                lstMonitorSensor.Remove(item);
            }
 

当调用List Remove 失效时 [C#] .的更多相关文章

  1. memcached缓存失效时的高并发访问问题解决

    memcached一般用于在访问一些性能相对低下的数据接口时(如数据库),为了保证这些数据接口的稳定性,加上memcached以减少访问次数,保证这些数据接口的健壮性.一般memcached的数据都是 ...

  2. Asp.Net调用Office组件操作时的DCOM配置 (转)

    Asp.Net调用Office组件操作时的DCOM配置 http://blog.csdn.net/gz775/article/details/6447758 在项目中将数据导出为Excel格式时出现“ ...

  3. embed元素 autostart false 失效时的解决方法

    embed元素 autostart false 失效时的解决方法 最近在工作中碰到了在网页中嵌入播放器播放声音文件的需求,最后使用了embed元素 代码如下: <embed src='1093. ...

  4. Rails : css或js文件无法成功预编译或调用jquery类插件时预编译问题

    调用bootstrap css框架时,将bootstrap文件夹放入 vendor/assets/下 bootstrap文件结构如下:    [shenma@localhost demo]$ ls v ...

  5. WebService调用一对多关联关系时出现 死循环:A cycle is detected in...

    通过WebService调用一对多关联关系时引起的问题:A cycle is detected in the object graph 具体异常信息: org.apache.cxf.intercept ...

  6. 调用具体webservice方法时时报错误:请求因 HTTP 状态 503 失败: Service Temporarily Unavailable

    添加web引用会在相应项目的app.cofig文件中产生如下代码: <sectionGroup name="applicationSettings" type="S ...

  7. ORA-39127: 调用 "WMSYS"."LT_EXPORT_PKG"."SCHEMA_INFO_EXP" 时发生意外错误

    expdp 告警提示: Export: Release 11.2.0.4.0 - Production on 星期日 4月 28 12:14:51 2019....ORA-39127: 调用 &quo ...

  8. C#调用Oracle的存储过程时,连接字符串需要配置PLSQLRSet=1

    C#调用Oracle的存储过程时, 如果有个SYS_REFCURSOR的Output参数存储时, web.config文件中的连接字符串需要配置PLSQLRSet=1, 否则可能会报这个错:参数个数或 ...

  9. dotnetcore ef 调用多个数据库时用户命令执行操作报错

    dotnetcore ef 调用多个数据库时用户命令执行操作报错 1.多个DbContext 时报错: 报错: More than one DbContext was found. Specify w ...

随机推荐

  1. sqoop 初用

    http://blog.csdn.net/dbanote/article/details/8907650 目前版本的Sqoop中,使用自由形式查询导入,只提供简单的查询,没有复杂的和“OR”条件查询在 ...

  2. MFC CString的L和_T

    这个问题困扰了很久,这个解释貌似好理解一些 L表示UNICODE串,比如wchar_t* str = L"yangsongx";_T在ANSI编译模式下表示ANSI串,在UNICO ...

  3. iOS 后台退出app时不执行applicationWillTerminate的临时解决方法

    - (void)applicationDidEnterBackground:(UIApplication *)application { // Use this method to release s ...

  4. 转】腾讯云CentOS 6.6安装 Nginx

    原博文出自于: http://www.cnblogs.com/xdp-gacl/p/5290155.html 感谢! 一.下载Nginx 从Nginx的官网(http://nginx.org/en/d ...

  5. JNLP + Applet + Bouncy Castle

    http://stackoverflow.com/questions/4275005/jnlp-applet-bouncy-castle ——————————————————————————————— ...

  6. HDU 1002 分类: ACM 2015-06-18 23:03 9人阅读 评论(0) 收藏

    昨天做的那题其实和大整数相加类似.记得当初我大一寒假就卡在这1002题上,结果之后就再也没写题... 到今天终于把大整数相加写了一遍. 不过写的很繁琐,抽时间改进一下写简洁一点. #include&l ...

  7. Cisco ASA5500系列防火墙恢复IOS全过程

    擦除防火墙配置的命令是write erase而不是erase flash!当ASA5510的flash被erase后,如何将新的IOS拷贝到5510内呢? 如下:1. 当flash被erase后设备会 ...

  8. HDU 4870 Rating(高斯消元 )

    HDU 4870   Rating 这是前几天多校的题目,高了好久突然听旁边的大神推出来说是可以用高斯消元,一直喊着赶快敲模板,对于从来没有接触过高斯消元的我来说根本就是一头雾水,无赖之下这几天做DP ...

  9. Eclipse报错 Unable to execute dex: Multiple dex files define Lcom/kenai/jbosh/AbstractAttr

    这个错误时jar包重复造成的!! 看看有没有多的private Libary  删除即可!!!

  10. ASP.NET|跳转(redirect)到其它站点,提示:当前线程终止。

    在XAF中,如果使用HttpContext.Response.Redirect()进行跳转,会出现”当前线程终止“的报错,跳转失败. 这时候,应该改用WebApplication.Redirect() ...