RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1607025
Accepted
Aycon
Aycon
Asked:2025-02-16 20:09:20 +0000 UTC2025-02-16 20:09:20 +0000 UTC 2025-02-16 20:09:20 +0000 UTC

在工厂方法中释放部分创建的对象的正确方法是什么?

  • 772

我有一个需要MyClass实例化A和初始化的类。所有三个类都继承了。我无法访问这些类的源代码,但是它们的构造函数可能会因某些参数组合而引发异常。我知道在构造函数中抛出异常是一种不好的做法,因为它可能会导致类在内存中处于不一致的状态(不变违反)。因此,我没有使用直接构造函数,而是使用在内部进行初始化的工厂方法,并且。如果至少有一个类,并且已引发异常,则该函数也会引发异常。我知道如果我无法创建,那么我至少应该释放该类并引发异常。我还知道,如果我无法创建该类,我至少应该释放先前创建的和,然后在中引发异常。BCIDisposableABCMyClass.Create()ABCCreateABCBACABCreate

请告诉我是否有一个好的模式或代码示例,如果我无法构建类,我该如何清除以前初始化的部分MyClass?
如果有多于三个部分怎么办?我正在考虑使用堆栈Stack<IDisposable>来清理各个部分。


应
@user7860670 的要求添加一个最低限度可重现的示例。看来这段文字太难理解了:

class A: IDisposable
{
  private readonly int p_value;

  public A(int value)
  {
    ArgumentOutOfRangeException.ThrowIfNegative(value);
    p_value = value;
  }

  public void Print()
  {
    Console.WriteLine($"Value is: {p_value}");
  }

  public void Dispose()
  {
    Console.WriteLine("A disposed");
  }
}


class B : IDisposable
{
  private readonly int p_value;

  public B(int value)
  {
    ArgumentOutOfRangeException.ThrowIfLessThan(value, 10);
    p_value = value;
  }

  public void Print()
  {
    Console.WriteLine($"Value is: {p_value}");
  }

  public void Dispose()
  {
    Console.WriteLine("B disposed");
  }
}


class C : IDisposable
{
  private readonly int p_value;

  public C(int value)
  {
    ArgumentOutOfRangeException.ThrowIfLessThan(value, 20);
    p_value = value;
  }

  public void Print()
  {
    Console.WriteLine($"Value is: {p_value}");
  }

  public void Dispose()
  {
    Console.WriteLine("C disposed");
  }
}

class MyClass
{
  private readonly A a;
  private readonly B b;
  private readonly C c;

  protected MyClass(A _a, B _b, C _c) { a = _a; b = _b; c = _c;}

  public MyClass Create(int _value)
  {
    // Maybe throw error
    A a = new A(_value);

    // Maybe throw error
    // Need free A
    B b = new B(_value);

    // Maybe throw error
    // Need free A
    // Need free B
    C c = new C(_value);

    return new (a, b, c);
  }
}
c#
  • 1 1 个回答
  • 70 Views

1 个回答

  • Voted
  1. Best Answer
    Alexander Petrov
    2025-02-16T22:11:58Z2025-02-16T22:11:58Z

    这个代码怎么样?

    public static MyClass Create(int value)
    {
        A a = null!;
        B b = null!;
        C c = null!;
    
        try
        {
            a = new A(value);
            b = new B(value);
            c = new C(value);
        }
        catch
        {
            a?.Dispose();
            b?.Dispose();
            c?.Dispose();
    
            throw new Exception("it's bad");
        }
        return new(a, b, c);
    }
    

    但更好的方法是抛弃工厂方法,在构造函数中执行初始化:

    class MyClass
    {
        private readonly A a;
        private readonly B b;
        private readonly C c;
    
        public MyClass(int value)
        {
            try
            {
                a = new A(value);
                b = new B(value);
                c = new C(value);
            }
            catch
            {
                a?.Dispose();
                b?.Dispose();
                c?.Dispose();
    
                throw new Exception("it's bad");
            }
        }
    }
    

    P.S. 该类本身MyClass应被制作成,并且在它的IDisposable方法中,Dispose免费a,,b。c

    class MyClass : IDisposable
    {
        ...
    
        public void Dispose()
        {
            a?.Dispose();
            b?.Dispose();
            c?.Dispose();
        }
    }
    
    • 2

相关问题

  • 使用嵌套类导出 xml 文件

  • 分层数据模板 [WPF]

  • 如何在 WPF 中为 ListView 手动创建列?

  • 在 2D 空间中,Collider 2D 挂在玩家身上,它对敌人的重量相同,我需要它这样当它们碰撞时,它们不会飞向不同的方向。统一

  • 如何在 c# 中使用 python 神经网络来创建语音合成?

  • 如何知道类中的方法是否属于接口?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5