Replies: 27 comments 6 replies
-
My opinion is that 95% of the time the singleton pattern is used, a better option is available. If a static class with static members is enough, I choose that over the singleton pattern. But when I want to use inheritance or interfaces, that does not work with a static class. I could then use the singleton pattern to solve that problem. I have never been sure there is any other use to this pattern (in C#). Please correct me if I am wrong. If I do not necessarily need shared members, I end up just creating multiple instances anyway. In some scenarios I use scoped dependency injection (e.g. SimpleInjector, Ninject(not my preference)), which injects a single instance of something or automatically makes a single instance e.g. for each web request. With all these options I end up rarely using the singleton pattern. I may be wrong, and it may be disparaging, but often I feel people use the singleton pattern, not because they have a good reason to use it, but just because it is the easiest pattern and then they can brag 'I use patterns' , 'I know patterns' even thought they only know the single pattern and then used it in a case where you don't need it. That feels kind of mean of me to my coworkers. I would like to be proved otherwise. In short: My opinion is that it the singleton pattern should not be that common, and is often misused, and so there is not much value to turn it into a language construct. But I invite you to prove me otherwise. |
Beta Was this translation helpful? Give feedback.
-
While I agree singletons aren't often used (as mentioned in the proposal) it's really an alternative to a static class that doesn't require decorating every single member with the static keyword and at the same time treats the class like any other (allowing for inheritance and interfaces). Maybe "public single MyType" or some other type specifier instead of singleton.. but I think the singleton keyword fits. |
Beta Was this translation helpful? Give feedback.
-
I do like your proposal, though. I vote for extending static classes with capabilities like inheritance and interfaces and that you can reference a static class as if it were a single instance. So instead of introducing a new singleton construct, extend static classes with those capabilities. |
Beta Was this translation helpful? Give feedback.
-
Extending static class would suffice but perhaps a new version of a static class is harder than using a new specifier? For example. we'd want this[] indexers as well but "this" doesn't make sense for a static type. Off the top of my head I can't think of other gotchas but there's bound to be some. It's a bit disappointing that we need to use "static" on every member at all when dealing with static classes as it's implied. |
Beta Was this translation helpful? Give feedback.
-
As I was listing out all the alternatives I used for singletons, I realized that I wish static classes could just do that. It is a drag when you realize your static class cannot be a static class anymore. I agree that the 'static' on all the static members seems rundandant and lot of typing or copy pasting for nothing. As for the 'this[]' indexers: This makes the case for changing indexers: #471 |
Beta Was this translation helpful? Give feedback.
-
I've updated the proposal thanks to your feedback @janjoostvanzon |
Beta Was this translation helpful? Give feedback.
-
'this[]' is in the way. But this[] is kind of an odd ball. The fact that you can use it in interfaces could be considered weird too, so perhaps we should accept this odd ball into new version of static classes too. Side-note: I am new to commenting here too. I subscribed to get notifications about csharplang, just out of interest, but I can't resist commenting on some of these issues. They really get into my head. |
Beta Was this translation helpful? Give feedback.
-
I want to point out that the Singleton pattern is quite different from static classes. Singleton designates a pattern for creation, and has nothing to do with how the class is consumed. The nature of a static class is such that it impacts every single client that uses it. To be more specific, after it has been created, a Singleton class may be passed around by its interface, and no one needs to know or care that it is a Singleton. This provides better flexibility and encapsulation. The "Singleton-ness" is an implementation detail. While I personally do not believe we need language level support for Singleton classes, I still see the occasional value of the pattern. It should not be confused with static classes, though, which are (merely) inflexible globals. |
Beta Was this translation helpful? Give feedback.
-
Thanks for your response. No offense, but I think insisting static classes and instance classes should be forever completely distinct from eachother, is a very inside-the-box thought. I know they are distinct, but if it were up to me, that distinction would be much less rigoureus. This is because conceptually, I already look at static classes as having just one instance of something. |
Beta Was this translation helpful? Give feedback.
-
@janjoostvanzon
That is not how they are designed or function. There are zero instances of a In my opinion the consumption of a singleton is an anti-pattern. That's not to say that singletons themselves are anti-patterns, only that the consumer should never know that the instance is a singleton. Any decent dependency injection container supports singleton scopes/lifecycles, and even if you don't rely on one it's quite easy to manage that yourself. Worst case, you write the convention above, and frankly having to write a private constructor, a property and a static field is far from onerous in terms of verbosity. It's also something very easily managed by a code snippet. |
Beta Was this translation helpful? Give feedback.
-
I'm glad to see this has at least generated a little discussion.
Well said @HaloFour - this fits with the problem that they're not exactly static classes
True, but the whole point of high level language is to remove such noise. Perhaps passing around a "this" pointer is far from onerous - and we don't have class methods. Perhaps passing around an array length is far from onerous - and we don't have safe arrays. I'm not saying a singleton type carries the same gravitas as the above examples, but the goal is to be explicit in our intent with as little distraction as possible. Thanks for all the feedback guys! |
Beta Was this translation helpful? Give feedback.
-
@janjoostvanzon,
I'd say you were out by 4.9999% there. (I would have gone for 5%, but it's good to allow for that "1 in a million" edge case...) |
Beta Was this translation helpful? Give feedback.
-
My concern with this idea is that most singleton's aren't. It's common to need a singleton per request or a singleton per thread, not just a singleton per process. Even for contexts where there would be exactly one instance in production, unit testing often requires a separate instance for each test, especially when using frameworks like I therefore suggest that singleton is more of a policy concern, not something that should be enforced by the language. |
Beta Was this translation helpful? Give feedback.
-
If I might come to the defense of singletons or a moment; they're very useful for type hierarchies that are a bit like an algebraic data type in that some 'cases' don't hold any data and therefore it would be very useful from a performance perspective to prohibit actually instantiating this type; instead all processing use the same, stateless, instance. For example, if you implement an option type as a type hierarchy: public abstract class Option<T>
{
private Option() { }
public class None : Option<T>
{
// ....
}
public class Some : Option<T>
{
// ....
}
} In this example Currently we need to do the implementation ourselves and then use It would be nicer if we could declare something like: public class object None
{
// ...
} and we can use it simply with Having said all this, I admit it's not a scenario that I see getting that much use (especially if we do eventually get discriminated unions in C#!), so maybe it's not worth implementing. It would be nice to have though. |
Beta Was this translation helpful? Give feedback.
-
I'm not sure many would argue that value singletons are a bad idea. They exist in many functional languages in the form of Nor are single instances of a type (ie, a singleton), that is injected throughout the rest of the code a bad idea. They are good, useful design. It is the singleton (anti) pattern that folk have a problem with. They really have no place in anyone's code, much less built in to the language as the OP requested. |
Beta Was this translation helpful? Give feedback.
-
I wanted to note that the required boilerplate for the singleton pattern can already be reduced significantly via existing language features: public class MySingleton {
public static MySingleton Instance { get; } = new MySingleton(1, 2);
private MySingleton(int x, int y) { ... }
}
I don't see how this proposal could allow for this. As soon as the constructor can be invoked externally the singleton enforcement is completely broken. It wouldn't be possible for multiple derived classes of the singleton class to "share" a base "instance". And by being UPDATE: Fixed static property to use readonly property initializer rather than expression bodied member. |
Beta Was this translation helpful? Give feedback.
-
@HaloFour are you sure that your code won't create a new instance every time you access the static propery? |
Beta Was this translation helpful? Give feedback.
-
Oops, you're right! Used the wrong syntax there. Will update. |
Beta Was this translation helpful? Give feedback.
-
The singleton pattern is broken, so it's only right that we share here, broken ways of implementing it 😉 |
Beta Was this translation helpful? Give feedback.
-
A bit of a tangent, but I do pretty much agree that singleton as a code pattern isn't a good idea. It's too constrictive and it causes issues of shared state. Singleton as a lifetime configuration combined with dependency injection is the way to go. |
Beta Was this translation helpful? Give feedback.
-
While I agree that the singleton design pattern doesn't have much of a place any more (not when lifetimes are typically managed by an IOC library or similar) but that doesn't mean that I don't want to support the concept of a single possible value in my domain code. I guess we need to distinguish between a singleton pattern and a singleton where the type & value are kind of the same because the class has no data and therefore only really one possible value (or, to put it another way, all instances of this type can be considered equal). Unit is the obvious example. It can be written in existing C# like this: public class Unit
{
public static Unit Instance { get; } = new Unit();
private Unit() { }
} but, I think it would be better and more consistent with discriminated unions (when they eventually appear) to have a special syntax for this type of class. I would write it like this: public object class Unit
{
} After this, the name "Unit" can be used as a type and a value: Unit x = Unit; What does this have to do with discriminated unions? Because the cases of a DU that do not define data are singletons, such as public enum class FavouriteColour
{
Red,
Green,
Blue,
Other(string)
} This could be written in longform: public abstract class FavouriteColour
{
public object class Red : FavouriteColour {}
public object class Green : FavouriteColour {}
public object class Blue : FavouriteColour {}
public class Other : FavouriteColour
{
...
}
} This is why I think this has a consistency value. To recap: It would be useful to have singletons in the language where a singleton is both a type and a value. |
Beta Was this translation helpful? Give feedback.
-
Completely agree. In my defence, I did say "singleton pattern", but it is all too easy for folk to go from "the singleton pattern is bad" to "thou shalt at all times have at least two instances of every type and value for singetons are evil and shalt not be tolerated". So your point is worth making. |
Beta Was this translation helpful? Give feedback.
-
I agree, and at that point we're not really talking about "singletons" as the design pattern but rather a way to work with type values. In my opinion I'm not convinced that the syntax gymnastics of companion objects are really necessary for this case. Specific cases like As for ADTs/DUs, that completely depends on how the team decides to implement them. IIRC F# completely fakes those values through |
Beta Was this translation helpful? Give feedback.
-
I'm glad you two agree on my distinction; indeed, depending on the implementation details of Discriminated Unions this feature may end up being--if not exactly DOA, then--rather pointless.
I don't think it is 😛 Unit is a type that has exactly one value: the empty tuple. You get it by taking the Cartesian product of zero sets. Undefined (aka Never) is the type that represents the empty set, and therefore has no values. So yes, |
Beta Was this translation helpful? Give feedback.
-
You make your point that this isn't an oxymoron, but the rest of your sample still doesn't make sense to me. Firstly, should the language team implement and support an official public unit WouldCompileFineIHope(string s)
{
Console.WriteLine(s);
// look ma, no return statement!
// the compiler will simply insert 'return default(unit);' for me
} |
Beta Was this translation helpful? Give feedback.
-
You make an interesting point around returns. I do, however think that Unit
is a special case and my ultimate hope is that Void gets promoted to a real
type in C# (and perhaps the runtime) so that existing, void-returning
functions written in previous versions of C# would not need to be changed
at all.
If we take Unit out of the equation then valueless returns, while sill
making sense, would probably be a bit too magic for most people.
As for value vs reference type, I think that most occurrences of this
feature would be value types for the efficiency reason, but I still see no
reason to restrict the feature to value types. My current thinking is that
there might still be some value in singletons that can participate in a
type hierarchy.
…On Thu, 18 Jan 2018, 17:09 Joe4evr, ***@***.***> wrote:
public static Unit Instance { get; }
You make your point that this isn't an oxymoron, but the rest of your
sample still doesn't make sense to me. Firstly, should the language team
implement and support an official Unit type, it's almost guaranteed to be
a value type (why would you *ever* want to incur a heap allocation for
it?). Secondly, and I've said this before: since there *is* only exactly
*one* value, then I really hope they make it that the compiler can just
infer to return *that* value whenever you specify that a method returns
unit.
public unit WouldCompileFineIHope(string s)
{
Console.WriteLine(s);
// look ma, no return statement!
// the compiler will simply insert 'return default(unit);' for me
}
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<https://github.com/dotnet/csharplang/issues/490#issuecomment-358714434>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAoyj6YIdJ1XAIbKBkET_2Kz1jLVkgjQks5tL3rIgaJpZM4NFWem>
.
|
Beta Was this translation helpful? Give feedback.
-
Recently I've come across needing to use singletons ever so often, including comparers implementing the Singletons would be a great niche feature to have in the language to avoid the utterly annoying public static LeafChildrenComparer Instance { get; } = new();
private LeafChildrenComparer() { } pattern, which was even worse before the |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Problem
C# programmers the world over often use the singleton pattern to overcome the shortcomings of static classes. Namely, that they don't behave like a class anymore.
It usually looks something like this;
Solution
While I'm not sure it's used enough to create elaborate compiler support, wouldn't it be nice to not repeat ourselves when using this pattern, while at the same time provide the gift of inheritance, interface implementation and indexer properties to these classes.
Simply by changing 'class' to 'singleton' this could be achieved.
This also has the added benefit of creating a static class that doesn't require every member to be prefixed with the static keyword as this should be implied.
Conclusion
This is my first proposal so be gentle. I know this is a low value add but every time I write the same pattern (which to be honest isn't that common in this case) I can't help but wonder if there should be an easier way.
Thanks!
Beta Was this translation helpful? Give feedback.
All reactions