c# - 我可以重写 Dispose 以创建一个始终调用 SaveChanges 的实体类吗?

标签 c# finalizer object-lifetime

这是一个相当好的观点,我希望答案是“一开始这不是一个热门的想法”——也就是说,如果有人愿意沉迷,它有一个我感兴趣的观点。

模型代码:

public partial class MyEntities : ObjectContext
{
    // the idea is if the object is in a using block, this always gets called?
    protected override void Dispose(bool disposing)
    {
        this.SaveChanges();
        base.Dispose(disposing);
    }
}

客户端代码:

using(var model = new MyEntities())
{
   // do something

   // no worry about calling model.SaveChanges()
}

我不确定的问题是:

  1. Dispose 是执行此操作的正确位置,因为出于某种原因我一直在考虑“完成”——我总是对 C# 销毁感到困惑。

  2. 如果在客户端代码中抛出异常,通常 SaveChanges 会被跳过,这很好,但如果这按我的想法工作,它总是会调用它。我应该使用带有空 catch 的 try 吗?

    public partial class MyEntities : ObjectContext
    {
        protected override void Dispose(bool disposing)
        {
            try
            {
               this.SaveChanges();
            }
            catch {}
            base.Dispose(disposing);
        }
    }
    

最佳答案

不要这样做。这是个坏主意。

“处置”的目的是尽早礼貌地处置非托管资源,以便其他进程可以使用它。 “Dispose”不应该有语义——它不应该改变你的程序的状态或者以某种方式被要求。它应该只按照它所说的去做:处理资源

你应该在终结器中这样做吗? 绝对不是。那更糟。终结器可能根本不运行,终结器在另一个线程上运行,即使对象未正确初始化也可以调用终结器,等等。 编写终结器几乎从来都不是正确的做法,如果您确实编写了终结器,它应该只处理资源。不要在终结器中做任何花哨的事情;如果这样做,您几乎肯定会编写出危险的不正确且脆弱的程序。

这里的正确原则是:如果出于语义原因需要调用,则强制用户将调用放入代码中。如果他们忘记这样做,他们会发现在测试中。 让用户决定将调用放在 finally block 中是否正确。不要替他们做决定;你可能会做出错误的决定。

关于c# - 我可以重写 Dispose 以创建一个始终调用 SaveChanges 的实体类吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7393692/

相关文章:

c++17: 一个从未被销毁的临时对象

c# - 是什么?是指类型之后?

c# - 为什么我们需要静态构造函数?

c# - 在 C# 源代码中断开长字符串的最佳方法

c# - 在 C# 中使用 Finalize/Dispose 方法

c++ - 将 "this"指针传递给析构函数中的其他类/函数

c# - 将 ObservableCollection 绑定(bind)到 ListBox 的选定项

Java 不释放带有 finalize() 覆盖的对象

c# - 在 Finalizer 中处理 MemoryCache 会抛出 AccessViolationException

c++ - 引用未命名的临时对象(生命周期)