Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 这是检查一个类是否只存在一个实例而不使用单例模式的好方法吗?_C#_Design Patterns_Singleton - Fatal编程技术网

C# 这是检查一个类是否只存在一个实例而不使用单例模式的好方法吗?

C# 这是检查一个类是否只存在一个实例而不使用单例模式的好方法吗?,c#,design-patterns,singleton,C#,Design Patterns,Singleton,我的程序中有一个类,我只需要一个副本。我不想使用单例模式,但有两个原因*见下文。我知道我将只有一个类的副本,因为我将是唯一一个调用其构造函数的人 在我的类的构造函数中,我想检查该类是否只存在一个副本,如果存在多个副本,则抛出异常。下面的代码是用于此案例的好模式吗 public class MySingletonAlternative : IDisposable { private static int _count = 0; public MySingletonAlternat

我的程序中有一个类,我只需要一个副本。我不想使用单例模式,但有两个原因*见下文。我知道我将只有一个类的副本,因为我将是唯一一个调用其构造函数的人

在我的类的构造函数中,我想检查该类是否只存在一个副本,如果存在多个副本,则抛出异常。下面的代码是用于此案例的好模式吗

public class MySingletonAlternative : IDisposable
{
    private static int _count = 0;

    public MySingletonAlternative()
    {
        int newValue = System.Threading.Interlocked.Increment(ref _count);
        if (newValue > 1)
        {
            throw new NotImplementedException();
        }
    }

    public void Dispose()
    {
        int newValue = System.Threading.Interlocked.Decrement(ref _count);
        if (newValue < 0)
        {
            throw new ObjectDisposedException("MySingletonAlternative");
        }
    }
}
*为什么我不想使用单例:

我希望能够控制类的创建时间。在传统的C单例模式中,构造是非确定性的

我想避免全局变量

当我调试代码时,在Singleton的私有构造函数中引发异常,VisualStudio会突出显示异常,但它会突出显示错误的代码行,通常在不同的文件中

我不想用Lazy懒洋洋地创建这个对象。这个类的一个实例将在我的应用程序的生命周期中存在。我懒散地建造它,一无所获


使用IoC容器,例如。它将删除您提到的为什么不想使用全局变量或静态变量的单例的所有要点。您将能够完全控制生命周期实例的创建,并将其注入到需要使用该实例的所有类中。

您可以使用依赖项注入,然后让di容器管理要创建的类的生命周期吗?Unity和ContainerControlledLifetimeManager就是一个例子

不要在实际应用中使用下面的代码!这只是为了演示的目的

我想这不是一个好方法,但看起来你的方法会很好地工作。但我不知道边缘案例

刚刚创建了一个小测试应用程序,在for循环和count中创建了100万个实例 它提出的例外情况。 在这种情况下,应该是:成功创建了1个实例,引发了999.000个异常

我运行了几次测试应用程序,它总是返回999.000。 根据您的机器,此代码可能需要一些时间才能完成, 因为它抛出999.000个异常

public static volatile int _global_Exception_count = 0;
static async Task Main(string[] args)
{
    _global_Exception_count = 0;

    var list = Enumerable.Range(1, 1000000).ToList();

    var tlist = list.Select(async item =>
     {
         MySingletonAlternative current = null;

         try
         {
             current = new MySingletonAlternative();
         }
         catch (Exception ex) { System.Threading.Interlocked.Increment(ref _global_Exception_count); }

         return await Task.FromResult(0);
     });
    await Task.WhenAll(tlist);

    Console.WriteLine(_global_Exception_count);
}// end main

如果您有一个静态构造函数,那么普通单例的构造是完全确定的。还有一个全局变量:计数器。根本不清楚为什么要阻止创建多个实例。这有一些单件模式的缺点,例如缺乏可测试性,没有一些可疑的好处。据用户所说,用户无法控制在程序中何时执行静态构造函数。另外,考虑到我已经宣布它是私有的,我不会称之为全球的。这是不真实的。对于不存在静态构造函数的类型,类型初始值设定项在某种程度上是正确的,但是当存在静态构造函数时,C规范非常明确:静态构造函数的执行是由应用程序域中发生的以下第一个事件触发的:-创建类类型的实例。-类类型的任何静态成员都被引用。实际上,该类没有理由关心存在多少其他实例。让类的用户决定如何最好地使用它。@user2023861不,您现在是实现者,以后是用户。您可以通过删除对实例数量的检查来简化类。如果您现在只需要一个实例,只需创建一个实例。如果稍后您决定需要两个实例,那么该类将允许您这样做。关键是,您可以将代码编写得简单灵活,也可以使其编写更复杂,使用更不灵活,当你意识到你真的想以稍微不同的方式使用它时,这可能会伤害到你——也许有不止一个实例存在——我认为依赖注入解决方案会比我需要的更健壮。我也不确定它是否能解决我的问题。我的项目很小,我不会经常更换组件或依赖项。我的问题最终是,在应用程序的生命周期中,我需要一个类的实例。此类保存一些数据并进行网络调用。我不想重复数据或不必要的网络呼叫;因此,只需将class.DI的一个实例添加到您的项目中并不大,也不难。根据您所说的,它将解决您列出的所有问题,而不仅仅是基于配置进行交换,而是让您以更易于测试的方式编写代码,同时消除单例类的固有缺陷,因为有可能为您管理应用程序的这一方面。事实上,如果您不习惯DI,那么在一个小项目中开始使用它是最容易掌握它的方法。不管怎样,祝你好运!有趣的是,我走的路
o使用MySingletonAlternative与我读到的依赖注入示例类似。直到你提到它,我才知道它叫那个。我在网上读到的例子对我来说似乎太健壮了,但是我想对需要我的生命周期对象的类做的是让它们有一个setter,我将使用它来设置依赖项,一旦它被构建,构建生命周期对象需要一点时间。谢谢,不是我。我甚至不记得我为什么问这个问题了。一个匿名的投票人从上到下对整个问题进行了投票。我很感激你的评论,至少有个理由。。。