0

今天我看到一个对我来说看起来非常可怕的剪辑,但不幸的是我不能简单地改变它,所以我想知道我是否可以通过某种方式绕过它。我有一个带有构造函数的类,该构造函数具有成功的输出参数。但这对我来说真的很难看。现在,当我从这门课上派生时,我必须随身携带这个参数——不管我想不想。

class ClassA {
    ClassA(out bool success) {...}
}

class B: ClassA {
    // call the constructor from ClassA but without the out-param
}

所以我会知道它是否是好的做法,或者如果不是,我如何避免从 ClassB 声明 out-param。

4

4 回答 4

3

虽然将参数refout参数传递给构造函数很丑陋,但在某些类型中,尝试创建可用实例会产生副作用,并且在其中一些副作用已经发生后可能会失败。如果不可能构造一个有效的对象,构造函数可以将信息传递给调用者的唯一方法是将其存储在一个threadstatic字段中,将其封装在抛出的异常中,将其存储或提供给传入的对象或委托,或将其写入ref/out参数。其中,只有ref/out参数表明存在客户端代码应该执行某些操作的信息。

ref或参数的存在out通常表明构造函数应该是protected,并且外部代码应该通过工厂方法来确保如果抛出异常,则传递的对象将得到适当的使用。然而,要使一个类合理地支持继承,它必须提供至少一个在其外部可见的构造函数。让该构造函数使用outorref参数可能是类让调用者知道如果构造失败需要清理哪些内容的最不邪恶的方式。

于 2013-10-28T16:45:00.933 回答
2

你可以这样做:

class ClassA
{
    protected ClassA(out bool success)
    {
        success = true;
    }
}

class B : ClassA
{
    [ThreadStatic]
    static bool success; // static to use in base(out success) call

    public bool Success
    {
        get;
        private set;
    }

    public B()
        : base(out success)
    {
        Success = success;
        success = false; // reset value
    }
}

这很难看,但如果你愿意的话,至少你可以去掉 out 参数。

于 2013-10-28T11:21:39.813 回答
0

好吧,该类的设计无论如何都被破坏了,所以让我们再破坏一下(注意!我不推荐这种方法!):

void Main()
{

}

public class ClassA
{
    public ClassA(out bool success)
    {
        success = true;
    }
}

public class B: ClassA
{
    private static bool success;

    // call the constructor from ClassA but without the out-param
    public B()
        : base(out success)
    {
    }
}

除此之外,您可以获得的最接近的是制作工厂方法:

public class B : ClassA
{
    public static B Create()
    {
        bool success;
        var result = new B(out success);
        if (success)
            return result;
        // TODO: Dispose result?
        throw new StupidProgrammerException();
    }
}
于 2013-10-28T11:21:23.250 回答
0

如果您真的不关心out参数的值,在较新版本的 C# 中,您可以声明一个out变量 inline 并且您可以选择不对其执行任何操作:

class B : ClassA
{
    B() : base(out bool ignore) { }
}

您可以更进一步并使用特殊的丢弃名称_让编译器知道您不会使用该变量。这样你甚至不需要声明它的类型:

class B : ClassA
{
    B() : base(out _) { }
}
于 2021-10-22T19:28:20.380 回答