Last active
August 29, 2015 13:58
-
-
Save controlflow/9996665 to your computer and use it in GitHub Desktop.
Possible C# primary constructors design
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Person : EntityBase { | |
// ~familiar syntax, no problems with xml doc, can omit body, can omit public? | |
public constructor(int id, string name, int age) : base(id); | |
readonly string _mrName = "Mr. " + name; | |
public string Name { get; } = name; | |
public int Age { get; } = age; | |
} | |
class Person { | |
// can change visiblity and add body for checks | |
private constructor(string name, int age) { | |
if (name == null) throw new ArgumentNullException("name"); | |
} | |
public Person() : this("Foo", 42) { | |
// secondary | |
} | |
public string Name { get; } = name; | |
public int Age { get; } = age; | |
} | |
class Component { | |
// explicit capture, can omit private when readonly | |
[ImportingConstructor] // no problems with attributes | |
public constructor([NotNull] readonly IFoo foo, [NotNull] readonly IBar bar); | |
public IFoo ExposedFoo => foo; | |
public void M(foo) { | |
// capture declares ordinary fields from class parameters, | |
// so conflicts with locals can be resolved by 'this.' qualifier | |
... this.foo ... | |
... bar ... | |
... | |
} | |
} | |
// placing primary constructor inside class body prevents from ability to put tons of code | |
// outside of class declaration body block, keeping class name and extends clause clear. | |
// I'm expecting silly classes like this: | |
class Component(IFoo dependency, IBar other, IBlah anotherOne) | |
: MySuperBaseType(dependency, other, anotherOne, (HowPeopleLove to) => { | |
put.LambdaExpressions(Inside.Base.Initializer); | |
InsteadOfOverridingMethods(); | |
HowIHateThis(); | |
}), ISomeInterface, IOtherInterface | |
{ | |
} |
In general I see primary constructors as something similar to autoproperties -- they are not a silver bullet for everything.
If you need something uncommon such as private constructor or event subscription in constructor, you can fall back to using normal constructor. Though if second part is common, it can be done by allowing a code block one way or another. I am just not sure it is common.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Attribute specifier "constructor:" exists in C#
Are you sure? C# 5 spec lists the following:
Provide you with examples of shitty code because you don't 'seen it at all'? Maybe you can just believe me, because I've already kill code like this in our code base?
Maybe it is specific to your codebase though, people just learning incorrectly from existing code. I do not disbelieve this exists, I am just trying to understand why anyone would use it.
It is hard to provide syntax for explicit body to do side-effects like argument checks and event subscriptions;
It is not that hard (just stuff the {} somewhere), but I would argue it is unnecessary for the primary constructor. You can always fall back to using normal constructor if you have complex logic. And argument checks can be easily provided btw:
XML documentation is the issue, you will unable to write famous useless summary like "Initializes the new instance of StringBuilder class";
As I said, and you say, this is useless, and especially useless for primary constructor.
It is hard to find a place for visibility modifier;
I agree, but I do not see a problem with limiting these to public (protected for abstract) as that would be most common use case. You can always just write a normal constructor if you want more control.
Class declaration upper side to looks messy - sometimes you will not be able to easily find base type specification or interface implementation;
This is subjective, I do not find your third example hard-to-read.
However, I do find this weird: