在 C# 中声明对象的正确位置
Correct place to declare a object in C#
我遇到过以下情况。
我的项目中有很多 class 文件,并且随着项目的增长,正在创建新功能,但没有正确的代码审查。因此,我们围绕同一个 class 创建了一些重复的对象(用于访问数据库,如控制器),但我们不知道只创建一个全局对象是否更好,还是应该保留它们在函数内部,因为有时代码不会到达那个函数,所以永远不会创建对象。如果是全局的,每次都会创建。
示例:
namespace EventWorks.View
{
public partial class Event : System.Web.UI.Page, ISecurityRules
{
protected void btnNew_Click(object sender, EventArgs e)
{
EventController EventCtrl = new EventController();
//some code
}
protected void btnSave_Click(object sender, EventArgs e)
{
EventController EventCtrl = new EventController();
//some code
}
}
}
我的问题是,我应该在哪里创建这些对象?最好在全球范围内创建它?还是将它留在函数内部,让垃圾收集器来处理?或者对每个文件进行大分析并检查哪个选项更好?
where should I create these objects?
这实际上取决于对象的责任、线程安全注意事项(如果有的话)以及创建此类全局成员的成本。没有 "yes make it global" 解决您所有问题的方法。您绝对应该分析您的所有成员,并为每个成员决定是否可以让它们全局可用以及它会对您的系统产生什么影响。例如,将 DbContext
作为单个实例在内存中保持活动状态将被视为不良做法,因为它不是线程安全的。
如果您只担心创建不必要的对象,您始终可以使用 Lazy<T>
class,这将确保该值仅在第一次访问时延迟初始化:
private readonly Lazy<EventController> eventController = new
Lazy<EventController>(x => new EventController(), isThreadSafe: true);
如果在多个函数中使用,它可以像这样在 class 级别上声明(那不是全局,而是 class 级别):
namespace EventWorks.View
{
public partial class Event : System.Web.UI.Page, ISecurityRules
{
EventController _eventController = new EventController();
protected void btnNew_Click(object sender, EventArgs e)
{
_eventController.DoSomething();
}
protected void btnSave_Click(object sender, EventArgs e)
{
_eventController.DoSomething();
}
}
}
也可以在构造函数中初始化,也可以通过依赖注入(构造函数、接口、setter注入)注入,我想这完全取决于你想要什么。
控制器通常会保留一些关于对象状态的信息。即,对象是新的还是从数据库加载的,是否有待处理的更改等等。
因此,拥有一个与对象具有相同生命周期的控制器似乎更合乎逻辑(每个对象都会创建一次)。
如果控制器不存储任何对象相关的东西,它可以在每个应用程序生命周期中创建一次。在这种情况下,您可以将其设为单例。
public class EventController
{
public static readonly EventController Instance = new EventController();
private EventController()
{
// Make constuctor private, so the class cannot be instantiated elsewhere.
}
// Implement functionality here...
}
这样称呼它:
EventController.Instance.DoSomething();
我遇到过以下情况。 我的项目中有很多 class 文件,并且随着项目的增长,正在创建新功能,但没有正确的代码审查。因此,我们围绕同一个 class 创建了一些重复的对象(用于访问数据库,如控制器),但我们不知道只创建一个全局对象是否更好,还是应该保留它们在函数内部,因为有时代码不会到达那个函数,所以永远不会创建对象。如果是全局的,每次都会创建。
示例:
namespace EventWorks.View
{
public partial class Event : System.Web.UI.Page, ISecurityRules
{
protected void btnNew_Click(object sender, EventArgs e)
{
EventController EventCtrl = new EventController();
//some code
}
protected void btnSave_Click(object sender, EventArgs e)
{
EventController EventCtrl = new EventController();
//some code
}
}
}
我的问题是,我应该在哪里创建这些对象?最好在全球范围内创建它?还是将它留在函数内部,让垃圾收集器来处理?或者对每个文件进行大分析并检查哪个选项更好?
where should I create these objects?
这实际上取决于对象的责任、线程安全注意事项(如果有的话)以及创建此类全局成员的成本。没有 "yes make it global" 解决您所有问题的方法。您绝对应该分析您的所有成员,并为每个成员决定是否可以让它们全局可用以及它会对您的系统产生什么影响。例如,将 DbContext
作为单个实例在内存中保持活动状态将被视为不良做法,因为它不是线程安全的。
如果您只担心创建不必要的对象,您始终可以使用 Lazy<T>
class,这将确保该值仅在第一次访问时延迟初始化:
private readonly Lazy<EventController> eventController = new
Lazy<EventController>(x => new EventController(), isThreadSafe: true);
如果在多个函数中使用,它可以像这样在 class 级别上声明(那不是全局,而是 class 级别):
namespace EventWorks.View
{
public partial class Event : System.Web.UI.Page, ISecurityRules
{
EventController _eventController = new EventController();
protected void btnNew_Click(object sender, EventArgs e)
{
_eventController.DoSomething();
}
protected void btnSave_Click(object sender, EventArgs e)
{
_eventController.DoSomething();
}
}
}
也可以在构造函数中初始化,也可以通过依赖注入(构造函数、接口、setter注入)注入,我想这完全取决于你想要什么。
控制器通常会保留一些关于对象状态的信息。即,对象是新的还是从数据库加载的,是否有待处理的更改等等。
因此,拥有一个与对象具有相同生命周期的控制器似乎更合乎逻辑(每个对象都会创建一次)。
如果控制器不存储任何对象相关的东西,它可以在每个应用程序生命周期中创建一次。在这种情况下,您可以将其设为单例。
public class EventController
{
public static readonly EventController Instance = new EventController();
private EventController()
{
// Make constuctor private, so the class cannot be instantiated elsewhere.
}
// Implement functionality here...
}
这样称呼它:
EventController.Instance.DoSomething();