[C#] как сделать синглетон? (ЗАКРЫТО)
using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
namespace xxx {
class CConcreteSingleton : CAbstractSingleton {
public static CConcreteSingleton getInstance {
return CConcreteSingleton.getInstanceOf(typeof(CConcreteSingleton;
}
}
}
Получаем:
Error 1 Cannot implicitly convert type 'xxx.CAbstractSingleton' to 'xxx.CConcreteSingleton'. An explicit conversion exists (are you missing a cast?) C:\Users\xxx\Documents\Visual Studio 2008\Projects\xxx\xxx\CConcreteSingleton.cs 11 20 xxxНаверняка ведь есть какой-нибудь способ сказать что-нибудь вроде AssertIs(Object, Type чтобы потом уже жить спокойно и чтобы компилятор-редактор ничего не говорили на попытки использовать объект в соответствии с этим типом?
return CConcreteSingleton.getInstanceOf(typeof(CConcreteSingleton;
return (CConcreteSingleton)CConcreteSingleton.getInstanceOf(typeof(CConcreteSingleton;
еще лучше getInstanceOf делать Generic и эту проверку переносить туда
тогда будет
return CConcreteSingleton.getInstanceOf<CConcreteSingleton>(typeof(CConcreteSingleton;
или вообще
return CConcreteSingleton.getInstanceOf<CConcreteSingleton>
ну и прогай дальше на пхп, сишарп видать не твое, как и вобщем - ООП.
если нормальный синглетон делается так:
[class]
class CConcreteSingleton
{
public static readonly CConcreteSingleton Instance = new CConcreteSingleton;
}
[/class]
особенно если учесть что код получился к тому же потоко-небезопасныйЭто пока что неважно
если нормальный синглетон делается так:Ага, и:
1) Какая-то не очень хорошая защита получается от того, что этот объект поменяют снаружи (хотя и есть какая-то защита в виде того, что конструктор закрыт, но тем не менее);
2) И когда все эти синглтоны заистанцируются? При запуске программы? В каком порядке они это сделают? Что, если конструктор одного синглтона будет использовать другой? В моей схеме всё будет работать, пока не будет кривых зависимостей (конструктор А использует Б в то время как конструктор Б использует А); а в твоём - видимо, не будет работать вообще.
Про generic-и сейчас читаю, пока что понятно только, что можно с их помощью сделать так, чтобы тип возврата getInstanceOf определялся при его вызове из конкретного getInstance; но непонятно, как можно избавиться от дублирования аргументов (чтобы писать, как ты сказал, CAbstractSingleton.getInstanceOf<CConcreteSingleton и как решить первую проблему...
Читаю дальше...
public static T Factory<T> where T:new
{
return new T;
}
Вообще, похоже, хрошая вещь эти generic-и...
сишарп видать не твоеНа основании чего ты сделал такой вывод?
Но код
abstract class CAbstractSingleton {
private static Dictionary<Type, CAbstractSingleton> hInstances = new Dictionary<Type, CAbstractSingleton>
abstract public static CAbstractSingleton getInstance;
protected static tClass getInstanceOf<tClass> where tClass : CAbstractSingleton, new {
if(!CAbstractSingleton.hInstances.ContainsKey(typeof(tClass {
CAbstractSingleton.hInstances.Add(typeof(tClass new tClass;
}
return CAbstractSingleton.hInstances[typeof(tClass)];
}
}
, что вполне естественно, не работает - в выражении return возвращается-то не tClass, а просто CAbstractSingleton.
Думаю дальше...
In the example above, class B is effectively both B and A. When you access a B object, you can use the cast operation to convert it to an A object. The B object is not changed by the cast, but your view of the B object becomes restricted to A's data and behaviors. After casting a B to an A, that A can be cast back to a B. Not all instances of A can be cast to B—just those that are actually instances of B. If you access class B as a B type, you get both the class A and class B data and behaviors.Но как-то это грязно...
Какая-то не очень хорошая защита получается от того, что этот объект поменяют снаружиКакой объект поменяют снаружи? Прочитай код, и подумай головой.
class CConcreteSingleton {
public static readonly CConcreteSingleton Instance = new CConcreteSingleton;
}
class COtherSingleton : CConcreteSingleton {
public COtherSingleton { }
}
class EvilDoer {
public void DoEvil {
CConcreteSingleton.Instance = new COtherSingleton;
}
}
Разве не сработает?
UPD: Не заметил слово readonly
Тем не менее, остальные минусы такого подхода остаются.
И когда все эти синглтоны заистанцируются? При запуске программы? В каком порядке они это сделают? Что, если конструктор одного синглтона будет использовать другой? В моей схеме всё будет работать, пока не будет кривых зависимостей (конструктор А использует Б в то время как конструктор Б использует А); а в твоём - видимо, не будет работать вообще.C# - это не php, здесь за тебя обо всём подумали. Статические конструкторы вызываются во время доступа к типу. Прежде чем начинать дискуссию, стоит прочитать какую-нибудь книжку по языку.
И когда все эти синглтоны заистанцируются? При запуске программы? В каком порядке они это сделают? Что, если конструктор одного синглтона будет использовать другой? В моей схеме всё будет работать, пока не будет кривых зависимостей (конструктор А использует Б в то время как конструктор Б использует А); а в твоём - видимо, не будет работать вообще.В этом подходе всё будет так же работать, как и в твоём, но код занимает гораздо меньше места.
Тем не менее, остальные минусы такого подхода остаются.Существенные минусы есть только в твоём подходе. Доступ не потокобезопасный, долгий, не предусмотрено создание класса, который не имеет конструктор по умолчанию. В то время как можно сделать синглтон с быстрым доступом и ленивой инициализацией.
return (tClass)CAbstractSingleton.hInstances[typeof(tClass)];
Прежде чем начинать дискуссию, стоит прочитать какую-нибудь книжку по языку.В этом-то и проблема, что под рукой нет никаких книжек, только мсдн. А решить задачу надо.
В этом-то и проблема, что под рукой нет никаких книжек, только мсдн. А решить задачу надо.Ну так набери в гугле "C# singleton" и почитай. Или не спорь с теми, кто читал книжки и знает, что делает.
Доступ не потокобезопасный, долгий, не предусмотрено создание классаДа я уже понял, что тот подход вроде как лучше, потому что там уже всё предусмотрено... но жопой чую, что что-то тут не так.
МБ со временем это пройдёт...
return (tClass)CAbstractSingleton.hInstances[typeof(tClass)];Я уже знаю, что так можно сделать, написал об этом в одном из предыдущих постов; но разве так - прилично делать?
Хм, про гугл я и не подумал
лучше б уж и вправду пейсал на пыхпыхе
Хм, про гугл я и не подумал
ты, походу, вообще не [по]думал
Уж лучше пусть пока будет максимально приближённое к тому, к чему я уже привык, а потом постепенно буду переходить на эти ваши новые фичи
Я уже знаю, что так можно сделать, написал об этом в одном из предыдущих постов; но разве так - прилично делать?почему нет?
ты как разработчик функции гарантируешь, что данный элемент словаря будет именно этого типа и данной конструкцией ты это рассказываешь компилятору.
соответственно - если ты компилятор обманешь, то просто будет exception.
Хотя, раз уж это можно решить так как ты сказал (с public static Instance = ... то, наверное, с таким извратом просто никто незаморачивался - чтобы достали чего-то из хэша, а оно оказалось конкретного типа.
гарантируешь, что данный элемент словаря будет именно этого типа и данной конструкцией ты это рассказываешь компиляторуА разве эта конструкция только объясняет компилятору про тип результата? Она же, наверное, ещё и преобразует объект в некоторых случаях? Или меня подводит семантика привычного языка?
А разве эта конструкция только объясняет компилятору про тип результата?в данном случае, только это
Она же, наверное, ещё и преобразует объект в некоторых случаях? Или меня подводит семантика привычного языка?да, она может неявно вызывать оператор преобразования (если он есть но такое поведение не принято в .net.
ты бы почитал соглашения по именованию для C#, а то методы с маленькой буквы, Object с большой, и какие-то буковки C.
Давайте я пока что не буду заморачиваться ещё и правильным именованием в C#?
Давайте я пока что не буду заморачиваться ещё и правильным именованием в C#?ну и зря, к таким мелочам лучше сразу привыкать, переучиваться сложнее. И потом твой код никто не будет читать, сразу впечатление, что ламер писал...
да, она может неявно вызывать оператор преобразования (если он есть но такое поведение не принято в .net.а ещё всегда будет выполняться проверка типа
к таким мелочам лучше сразу привыкать, переучиваться сложнееПереучиваться с нынешнего стиля именования мне в любом случае придётся; и, наверное, лучше переучиваться тогда, когда я начну активно использовать C# и перестану использовать PHP?
Оставить комментарий
kruzer25
Я тут уже все мозги сломал, пытаясь придумать, как бы решить эту проблему... наверняка в мсдн что-то про это написано, но надо придумать, по каким ключевым словам искать...Что естественно - выдаётся ошибка
и
, в результате - ничего не компилируется.
Как ей можно сказать, что oCreatedSingleton всё-таки является объектом CAbstractSingleton?
Закоменченную строчку не проверял, но выглядит уж очень страшно, и кажется, что преобразование CConcreteSingleton в CAbstractSingleton ни к чему хорошему не приведёт.
Да, и ещё - это я тут, может быть, просто пытаюсь всё сделать, как в пхп, а на самом деле всё это реализуется в C# в две строчки, если ещё не входит в BCL? Правда, в мсдн ничего полезного по запросу singleton найти не удалось.