定义了类Class1,代码如下所示:    class Class1
    {
        private WebBrowser webBrowser = new WebBrowser();        public void method()
        {
            webBrowser.Name = "";
        }
        
    }编译时出现了下面的警告:“警告 1 CA1001 : Microsoft.Design : 在 'Class1' 上实现 IDisposable,因为它创建下列 IDisposable 类型的成员: 'WebBrowser'。 E:\Work\WindowsFormsApplication7\WindowsFormsApplication7\Class1.cs 9 WindowsFormsApplication7”
我知道,这个原因是没有释放webBrowser这个非托管资源。我该怎么写代码去释放它呢?

解决方案 »

  1.   

    让Class1继承IDisposable接口,在Dispose方法内调用webBrowser.Dispose();从而释放掉webBrowser所引用的非托管资源
      

  2.   

    实现IDisposable接口,实现Dispose()方法
      

  3.   

    可以麻烦您具体写一下代码吗?MSDN上也是这么说的,但是我没有见过实际的代码,我自己写了,只是编译能通过,实际是否释放没有也没法验证。谢谢了!
      

  4.   

    我现在的代码修改成了下面的方式:
       class Class1:IDisposable
        {
            private WebBrowser webBrowser = new WebBrowser();        public void method()
            {
                webBrowser.Name = "";
            }        public void Dispose()
            {
                webBrowser .Dispose ();
            }     
        }虽然不再有CA1001警告了,但是查看MSDN,了解到还需要考虑使用GC.SupressFinalize()方法、需要根据disposed属性做判断,以及需要考虑写析构函数~Class1()。
    请高手能给解释下吗?最好能贴上代码,非常感谢!
      

  5.   

    自己尝试着模仿MSDN上的写法,写了释放的代码如下:    class Class1:IDisposable 
        {
            bool disposed = false;
            WebBrowser wb = new WebBrowser();
            public void method()
            {
                wb.Name = "";
            }        public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(wb);//将非托管的wb从finalization请求队列中排除
                                              //以防止GC重复回收
            }        private void Dispose(bool disposing)
            {
                if (!this.disposed)//Dispose()方法还没有调用过
                {
                    if (disposing)
                    {
                        //在这里释放托管对象
                    }
                    wb.Dispose();//采取适当的方法释放非托管对象,我这里用的是dispose,
                                     //根据不同的对象应该具体使用不同的方法
                    disposed = true;
                }
            }
            ~Class1()//模仿着写的析构函数,我没有想明白是为什么,疑惑大大的有!!!
            {
                Dispose(false);//在这里不要再写释放的代码。
                                   //为了可读性和可维护性,微软建议只是调用Dispose(false)就OK了!
            }
        }在注释中写的是我对MSDN中描述的理解,看到英文头就大,不知道理解得对不对?这么写还有哪些不恰当的地方,盼高手指教、斧正!
    另外还有一个疑问:~Class1()这里写个析构函数是干什么用的??既然要求用户代码中手动调用Dipose()方法,那么为什么还会需要写这个将会被自动调用的析构函数?
      

  6.   

    class Class1 : IDisposable
        {
            private bool disposed = false;
            WebBrowser wb = new WebBrowser();
            public void method()
            {
                wb.Name = "";
            }        public void Dispose()
            {
                Dispose(true);//调用带参数的Dispose方法,释放托管和非托管资源            GC.SuppressFinalize(wb);//手动调用了Dispose释放资源,那么析构函数就是不必要的了,这里阻止GC调用析构函数        }        //protected的Dispose方法,保证不会被外部调用。传入bool值disposing以确定是否释放托管资源
            protected void Dispose(bool disposing)
            {
                //
                if (!disposed)
                {
                    if (disposing)
                    {
                        //在这里释放托管对象;应该是xxx.Dispose();
                    }
                    wb.Dispose();//采取适当的方法释放非托管对象,我这里用的是dispose,
                    //根据不同的对象应该具体使用不同的方法
                }
               disposed = true;
            }        //供GC调用的析构函数
            ~Class1()
            {
                Dispose(false);//释放非托管资源        }
        }
    这么写是结合了析构函数和Dispose()的优点,逻辑有点复杂,其实很简单,如果你显示调用了Dispose()方法来清理资源,他会清理掉托管和未托管资源;如果你没调用Dispose(),垃圾回收器将调用析构函数,本来析构函数只能清除托管资源,但是在析构函数内部调用了Dispose(bool)方法,他就能清除掉托管和未托管资源。你重点理解下中间那个Dispose(bool)方法,把他的逻辑弄明白了,你也就搞清楚了。
      

  7.   

    嗯,应该是如你所说的道理!按照你所说,虽然微软要求(建议)在用户代码中手动调用dispose(),但是即使用户没有调用,GC也会根据析构函数去执行dispose()。果真如此,我算是都想明白了!非常感谢回帖的朋友,特别是7楼!
    再等下,等到明天,如果没人有不同意见了,就结贴。
      

  8.   

    再仔细琢磨了下在这里写下析构函数的道理,感觉这正是MSDN代码的“优雅”之处。其实C#.net的东西,就是微软制定的规则,就好比交通规则要求行人靠右一样,遵守交通规则、靠右侧走的行人,是个“优雅”的行人,可以增加城市交通的观赏性;而不靠右侧走、到处乱窜的行人,是个“鲁莽”的行人,会影响市容市貌;如果是“鲁莽”的代码,别人看着不顺眼,自己看着也别扭,将会给项目今后的阅读、维护带来困难。
    呵呵,题外话了。