我所有的参数都应该在构造函数中

本文关键字:构造函数 参数 | 更新日期: 2023-09-27 18:06:29

我有一个类StreamCopyOperation,它为我提供了诸如复制操作的平均速度和其他信息。

现在我有了一个构造函数,看起来像

public StreamCopyOperation(Stream source, Stream target, int bufferSize, int updateInterval)
{
    //Initialize values
}

和方法

public void CopyStream()
{
    //Copy the streams, send the progress updates, etc...
}

现在我不知道是否所有的参数都应该在构造函数中还是应该像这样在方法中传递流:

public void CopyStream(Stream source, Stream target)
{
    //Copy the streams, send the progress updates, etc...
}

,构造函数只获取缓冲区大小和传递的更新间隔。或者一切都应该在CopyStream方法中。

是否存在类似于最佳实践的东西,或者这只是一个设计决策?

我所有的参数都应该在构造函数中

我认为这是一个基于你期望如何使用类的设计决策。

如果它是一个一次性使用的类类型,那么也许所有的参数都应该传递给构造函数,然后你设置任何其他属性,然后调用CopyStream(不带参数)。

但是,如果您希望流参数改变,那么不要将它们传递给构造函数,而是将值传递给CopyStream方法。

最后,如果它确实是一个一次性使用类型的类,那么也许您应该考虑这个类是一个static类,而CopyStream是静态的——这样可以节省一行代码,并使这个类更像一个helper类型的类。

希望这对你有帮助!

在我看来,这将取决于StreamCopyOperation对象的生存期…

特别是,由于流对象通常(总是?)是一次性的,并且绑定到一些系统资源,我希望尽可能少地保留它们,因此我会考虑采用参数化方法。

如果StreamCopyOperation只绑定到流本身的生命周期,那么第一种方法是合适的。

但是如果你想让操作对象保持更长时间(例如,因为它连接到UI),那么我将使用参数化函数方法,并进入更多的静态"助手类"。

这取决于您期望如何使用CopyStream。它是经常使用的东西吗?这将建议使用CopyStream方法的方法参数。如果它被设计为一次性调用,那么在启动您的类型的新实例时使用构造函数参数。

如果你要在类作用域中使用这些Stream,如其他方法,最好将它们作为构造函数参数传递,并将它们赋值给在类作用域中声明的变量,否则不需要将它们传递给构造函数,建议使用第二个CopyStream方法。

我认为这是一个设计决策。

如果CopyStreamOperator的单个实例没有被多个源和/或目标重用,我可能会在构造函数中传递所有必需的值,以创建一个知道它需要知道的一切的对象。然后可以验证输入值,以确保操作符永远不会处于无效状态。

然后将无参数的CopyStream()方法重命名为Run()Execute()

我会考虑对不那么重要的细节使用默认值,并在类中为这些细节提供属性来设置或获取它们的值:

private const int DEF_BUFFER = 100;
private const int DEF_INTERVAL = 10;
public StreamCopyOperation(Stream source, Stream target)
{
   //Initialize values
   this.BufferSize = DEF_BUFFER;
   this.UpdateInterval = DEF_INTERVAL;
} 
public int BufferSize { get; set;} // or use a private member inside, if needed
public int UpdateInterval { get; set;} // or use a private member inside, if needed

我的设计原则是只要求用户提供构造实例所绝对需要的构造函数。也许用户不想要进度更新。当用户想要构造实例并连接进度事件时,可能还没有两个流。

当然,你可以提供方便的构造函数重载(或可选参数),以便在更多情况下更容易使用你的类(但这些可以推迟到"构造方法",例如TimeSpan.FromMinutes(5))。但是请记住,构造函数的目的是简单地创建和初始化类型及其所有子系统,使其处于可用的、一致的状态,随时准备执行用户的命令。

当然,不可变类型是例外,必须在构造过程中指定所有参数。通常不可变类型相当简单,所以这不是问题。如果它们更复杂,并且构造函数参数的数量超出了控制,你可以使用一个可变的"初始化说明符"对象,它包含了如何初始化不可变对象的所有各种配置,但由于它具有可变属性,因此更容易使用。