1. C# / Говнокод #14286

    +138

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    /// generic Singleton<T> (потокобезопасный с использованием generic-класса и с отложенной инициализацией)
     
    /// <typeparam name="T">Singleton class</typeparam>
    public class Singleton<T> where T : class
    {
      /// Защищённый конструктор необходим для того, чтобы предотвратить создание экземпляра класса Singleton. 
      /// Он будет вызван из закрытого конструктора наследственного класса.
      protected Singleton() { }
     
      /// Фабрика используется для отложенной инициализации экземпляра класса
      private sealed class SingletonCreator<S> where S : class
      {
        //Используется Reflection для создания экземпляра класса без публичного конструктора
        private static readonly S instance = (S) typeof(S).GetConstructor(
                    BindingFlags.Instance | BindingFlags.NonPublic,
                    null,
                    new Type[0],
                    new ParameterModifier[0]).Invoke(null);
     
        public static S CreatorInstance
        {
          get { return instance; }
        }
      }
     
      public static T Instance
      {
        get { return SingletonCreator<T>.CreatorInstance; }
      }
     
    }
     
    /// Использование Singleton
    public class TestClass : Singleton<TestClass>
    {
        /// Вызовет защищенный конструктор класса Singleton
        private TestClass() { }
     
        public string TestProc()
        {
            return "Hello World";
        }
    }

    Код из Википедии. Создание синглтона на шарпике с излишествами и извращениями

    В самом деле, кому нужна инкапсуляция, нам же нужен синглтон

    P.S может я чего не понимаю.

    Запостил: kegdan, 26 Декабря 2013

    Комментарии (30) RSS

    • А что это все молчат?
      Ответить
      • Надо было пустой коммент писать вовремя :)
        Ответить
      • Ну а че тут сказать... в шарпе есть более адекватные способы запилить синглтон?
        Ответить
        • class SomeSingleton
              {
                  private static SomeSingleton _instance;
                  private SomeSingleton(){}
                  public static SomeSingleton Instance
                  {
                      get { return _instance ?? (_instance = new SomeSingleton()); }
                      private set {}
                  }
              }


          Так например
          Ответить
          • private SomeSingleton(){} и private set {} лишнее
            Ответить
            • конструктор по умолчанию публичный. как и сеттер. так что все верно
              Ответить
          • > ??
            a ?? b = a !=null ? a : b (аля coalesce в sql) или я туплю?

            P.S. Этот код не потокобезопасен.
            Ответить
            • >> a ?? b = a !=null ? a : b

              именно

              >> Этот код не потокобезопасен

              Большенству синглтонов не нужна потокобезопасность, так как, как правило, состояние его не изменяется. В примитивном случае можно залочить типом
              Ответить
              • > именно
                Удобный сахарок.

                > Большенству синглтонов не нужна потокобезопасность
                Большенство синглтонов вообще нинужно.

                > состояние его не изменяется
                А при чем тут его состояние? Я о потокобезопасности получения инстанса синглтона, а не о его собственной потокобезопасности.
                Ответить
                • >Большенство синглтонов вообще нинужно

                  В это смысле я сам больше предпочитаю статичный класс)

                  > А причем тут его состояние? Я о потокобезопасности получения инстанса синглтона, а не о его собственной потокобезопасности.

                  Да я уже понял свою ошибку. Но время на редактирование дают чертовски мало
                  Пример ниже

                  Или можно так
                  public class Singleton
                  {
                      private Singleton() { }
                  
                      private sealed class SingletonKeeper
                      {
                          public static readonly Singleton Instance = new Singleton();
                      }
                      public static Singleton Instance
                      {
                          get { return SingletonKeeper.Instance; }
                          private set { }
                      }
                  }
                  Ответить
                  • Ну вот с кипером да, вроде норм. В жабе примерно так же делают. В теории должно работать пошустрее, чем лок.

                    > В это смысле я сам больше предпочитаю статичный класс)
                    Не-не-не Девид Блейн. Класс с паблик статик методами на порядок хуже синглтона...

                    Когда ты, внезапно, понимаешь, что тебе нужно 2 инстанса синглтона, тебе надо переделывать только точки, где получают инстанс синглтона. Работа с его методами и свойствами не меняется.

                    Когда ты, внезапно, понимаешь, что тебе нужно 2 инстанса класса со статиками - ты в жопе.

                    P.S. Естественно я не предлагаю переделывать сборники статических методов (не юзающих никакого состояния) и констант в синглтон ;) Я все-таки о объектах с достаточно сложной логикой, где эти статические методы работают со статическим же состоянием.
                    Ответить
                    • С DoubleSingleton еще не сталкивался - студент-с. Точнее с запилом его из обычного)

                      Некоторые все стараются синглтоном заделать - например класс констант в каком нибудь модуле. Я просто статичный класс пишу
                      Ответить
                      • Не, ну класс констант и класс, в котором просто пачка чистых статических методов в синглтон пихать - верх идиотизма ;)

                        Я вот про какие случаи: чел думает, что его прога будет юзать только один инстанс скриптового движка. Из лени он загоняет этот инстанс в синглтон "шоб и с DI не трахаться и руками ссылку не таскать". Внезапно задание меняется, и ему нужно два-три параллельно работающих инстанса движка...
                        Ответить
                        • Ну мне кажется это не самое страшное)
                          Я вот писал тестовое задание (все по техам) а потом вдруг оказалось, что у работодателя "особое видение" интерфейса, которое он, почему то, не мог описать. А если учесть, что задание - граф. редактор и View-Controller занимает больше 2/3...)
                          Ответить
                          • > работодателя "особое видение" интерфейса, которое он, почему то, не мог описать
                            Заказчик никогда не может описать интерфейс. Да и не должен, если он все время этим не занимается... Ты должен показать ему сляпанный за пару дней набросок, и спросить, устраивает ли это его...
                            Ответить
                            • Тут у заказчика было четкое представление интерфейса, но описал от все очень абстрактно. Собственно когда я сделал набросок, у меня вежливо поинтересовались - "почему не так, как у нас в голове?"
                              Ответить
                              • > Собственно когда я сделал набросок, у меня вежливо поинтересовались - "почему не так, как у нас в голове?"
                                Ну так для того и нужен набросок, чтобы синхронизировать мысли заказчика и мысли разработчика прежде чем начинать писать все по-серьезному ;) Что тебе не понравилось то? :)
                                Ответить
                                • А еще естьзаказуны которые точно знают как должно выглядеть на этой недели. На следующей он высмотрит что то другое и тоже будет знать как должно быть. Тут надо вовремя послать на ЙУХ
                                  Ответить
                                  • > Тут надо вовремя послать на ЙУХ
                                    Ну да. Просто, когда прототип показываешь, что-то менять - вполне нормально и адекватно. А когда уже все запилено - да, жопа.
                                    Ответить
                                  • Лол, пыхобыдло про сиьшарп говорит
                                    Ответить
            • Что то типа
              lock (typeof (SomeSingleton))
                          {
                              return _instance ?? (_instance = new SomeSingleton());
                          }
              Ответить
              • Хе, а можно:
                private static readonly Lazy<SomeSingleton> _instance = new Lazy<SomeSingleton>(()=> new SomeSingleton(), true);

                public static SomeSingleton Instance
                {
                get {return _instance.Value;}
                }

                И все заморочки. Не нужна потокобехопасность - просто заменить true на false.
                Ответить
            • Ух. Да это даже круче чем
              int a = <something>;
              bool b = !!a;
              Ответить
              • Всмысле?
                Ответить
                • В смысле не очевидно.
                  Во-вервых, не все знают, что делает a??b (если не ошибаюсь, a!=null?a:b), во-вторых некоторые (вроде меня :) ) только что узнали, что ?? может быть lvalue, а в-третьих, болезнь всех lvalue, отличных от переменных - хрен поймёшь, куда же оно таки присвоилось.
                  Ответить
                  • Но здесь же его не используют как lvalue :)
                    Я поюзал = в его математическом смысле, просто спросив, что a ?? b это тож самое, что и a != null ? a : b...

                    P.S. Не знаю как в шарпе, но в сишке можно и так: x = (b ? sin : cos)(x)
                    Ответить
                    • Да, пардон )
                      Проверил сейчас на всякий случай - ведёт себя как rvalue
                      Ответить
                    • прямо так нельзя - ибо транслятор в Cil требует законченного выражения

                      если хочется аргументы один раз в конце - можно вот так извратится

                      var a = new Func<double, double>(s=>b ? Math.Cos(s) : Math.Sin(s)).Invoke(x);
                      Ответить

    Добавить комментарий