【问题标题】:Singleton without sealed class and thread safety issues没有密封类和线程安全问题的单例
【发布时间】:2019-06-21 13:52:46
【问题描述】:

我在今天的采访中被要求写 Singleton。我写了以下内容,请注意,我使用“属性集”方法进行设置,然后使用“获取”方法返回实例。但是我在互联网上看到他们使用的大多数地方只能得到,意思是,我在下面做错了什么?抱歉,我现在没有 VS ide 来验证它,所以在这里发布。

另外,一些使用密封类,包括私有构造函数。为什么要用私信封印?

public class Singleton
{
   private static readonly Singleton instance;

   private Singleton() {}

   public static Singleton Instance
   {
       set
       {
         if(instance == null){
            instance = new Singleton();
         }
       }
       get
       {
                  return instance;
}

   }
}

【问题讨论】:

  • 拥有这样的set 会误导 IMO。这显然不是要使用 value 并忽略它。您在 setter 中所做的一切都可以在 getter(或实例声明)中完成。不过,您可以在多个“级别”中创建单例。在此处查看 Skeet 的答案:stackoverflow.com/a/2667058/2957232。我特别建议您也访问那里的链接网站;它有一些极好的深入信息。
  • @BrootsWaymb:谢谢。面试官说少了点东西哈哈。好吧,我不知道它是对还是错,至少考虑一下。但是如果你说这段代码是错误的(在语法上或概念上),那么我想我会在这个问题上失去可信度。无论如何我都会阅读上面的链接
  • 哦,忘了说代码最大的直接问题是instance被标记为readonly,所以它不能存在于setter中。至于sealed 的事情,请阅读他回答中的链接。它解决了这个问题。
  • Why sealed with private cons? 阻止任何其他类新建第二个实例。
  • 是的。您可以继承该类,因此拥有“两个”类。

标签: c# .net c#-4.0 singleton private-constructor


【解决方案1】:

我的建议是尝试自己编译和运行代码。这是迄今为止了解其工作原理的最简单方法。

如果您尝试构建您的代码,您会收到以下错误:

Error   CS0198  A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)

换句话说,您应该在构造函数中实例化您的实例。

关于您的问题,需要一个私有构造函数来防止从您的类外部访问,并且足以确保其他类不能从您的类继承。你真的不需要密封的。

你可以找到关于单例模式的非常好的总结@https://csharpindepth.com/articles/singleton

【讨论】:

  • 感谢您的见解和时间。我的个人计算机中没有 IDE。我有但还没有许可证密钥。是的,在我的面试中,很多问题都是用普通的 A4 纸写的,我被要求为所有这些问题编写程序。大多数问题我喜欢 80%,少数问题喜欢 100%。
  • @CamiloTerevinto 但他们现在这样做了。他们不可能在面试中使用 IDE 来获得这个答案,但他们不需要再问关于 SO 的问题来让别人为他们编译代码。
  • @Learner VS 社区版不需要任何密钥。
  • @Servy:当然,我会尝试下载。谢谢你。星期六午夜 12.26 点哈哈,我会看看我是否可以至少在几天内下载和学习,哈哈这对我有帮助
  • And yes, in my interview, so many questions were in plain A4 sheet and I was asked to write programs for all those questions 这绝对是一种糟糕的面试技巧。我不会在没有计算机的情况下编写软件——我当然不会指望我想雇用的人这样做。
【解决方案2】:

@Learner 因为这是一个面试问题,而且大多数在印度,他们要求写 Psuedo 代码来评估候选人的编码技能,所以我试着让自己适应候选人的鞋子来给出答案。

随着编程语言的进步,设计模式已经发展了一段时间,Singleton 也不例外。我们可以通过多种方式使用 C# 创建 Singleton 类。我想展示一些我能记得的口味

1.没有线程安全的普通香草单例

public sealed class Singleton  
{  
    private Singleton()  
    {  
    }  
    private static Singleton instance = null;  
    public static Singleton Instance  
    {  
        get  
        {  
            if (instance == null)  
            {  
                instance = new Singleton();  
            }  
            return instance;  
        }  
    }  
}

2。带线程安全的单例

public sealed class Singleton_ThreadLock
{  
    Singleton_ThreadLock()  
    {  
    }  
    private static readonly object padlock = new object();  
    private static Singleton_ThreadLock instance = null;  
    public static Singleton_ThreadLock Instance  
    {  
        get  
        {  
        // Uses the lock to avoid another resource to create the instance in parallel
            lock (padlock)  
            {  
                if (instance == null)  
                {  
                    instance = new Singleton_ThreadLock();  
                }  
                return instance;  
            }  
        }  
    }  
} 

3.单例 - 双线程安全

public sealed class Singleton_DoubleThreadSafe  
{  
    Singleton_DoubleThreadSafe()  
    {  
    }  
    private static readonly object padlock = new object();  
    private static Singleton_DoubleThreadSafe instance = null;  
    public static Singleton_DoubleThreadSafe Instance  
    {  
        get  
        {  
            if (instance == null)  
            {  
                lock (padlock)  
                {  
                    if (instance == null)  
                    {  
                        instance = new Singleton_DoubleThreadSafe();  
                    }  
                }  
            }  
            return instance;  
        }  
    }  
}

4.单例 - 早期初始化

public sealed class Singleton_EarlyInitialization  
{  
    private static readonly Singleton_EarlyInitialization instance = new Singleton_EarlyInitialization();
    // Explicit static constructor to tell C# compiler  
    // not to mark type as beforefieldinit  
    static Singleton_EarlyInitialization()  
    {  
    }  
    private Singleton_EarlyInitialization()  
    {  
    }  
    public static Singleton_EarlyInitialization Instance  
    {  
        get  
        {  
            return instance;  
        }  
    }  
}  

5. Singleton - 使用 .Net 4.0+ 框架进行延迟初始化

public sealed class Singleton  
{  
    private Singleton()  
    {  
    }  
    private static readonly Lazy<Singleton> lazy = new Lazy<Singleton>(() => new Singleton());  
    public static Singleton Instance  
    {  
        get  
        {  
            return lazy.Value;  
        }  
    }  
}

注意事项:

  1. 嗯,很少有人使用反射创建类的实例(我在我的一个框架中做过),但他也可以避免。网络中很少有样本可以显示如何避免它
  2. 将 Singleton 类设置为密封的始终是最佳实践,因为它会限制开发人员继承该类。
  3. 市场上有很多 IOC 无需遵循上述 Singleton 实现即可创建普通类的 Singleton 实例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多