7 Features I Wish C# Had
A while ago I saw StackOverflow question What enhancements do you want for your programming language?. I was able to, to my surprise, actually come up with something, but to be honest I don’t really think very much about what in my current programming language should be changed. Don’t get me wrong, I bitched and moaned about Visual Basic for about a decade, but it wasn’t that I wanted VB ‘changed’; I just didn’t want to work in it at all. But I digress, actually, you may want to avoid me if I ever get on the topic.
This question about what I would like to see in a programming language is something I’ve thought about, since, but the only real features I can think of consist around building a domain specific language around a specific industry and methodology. I think it would be cool to build a language around a technical analysis technique called Elliot Wave for example.
More recently, I’ve heard Jeff Atwood assert, on the StackOverflow podcast, that any good programmer can whip off 10 things they hate about their favorite programming language in a flash.*
I couldn’t come up with 10 things I hate, so I’m going to settle for 7 features I’d like to see. There may be good reasons why we don’t have some of them, but here’s my list anyway:
1. Parameter constraints
One of the first things I learned to do when I started programming, is to validate the parameters. This has saved me untold hours of debugging and I currently start every method with something like:
1 2 3 4 5 6 7 8 9 10 11 12 13 | void DoSomething(float percentage, string userName) { if (0 > percentage || 100 < percentage) throw new ArgumentOutOfRangeException(); if (string.IsNullOrEmpty(userName)) throw new ArgumentNullException(); if (0 > userName.Length) throw new ArgumentNullException(); if (userName.Equals("Guest")) throw new ArgumentException("User must log in."); // .... do stuff } |
This is in almost every method. So why can’t the language do this for me automatically?
Yes, I know about declarative programming, but isn’t that just pushing it into the attributes? Where a 3rd party tool will process it?
What I’m suggesting is something similar to the generics keyword ‘where’. Why not have something like this:
1 2 3 4 5 | void DoSomething(float percentage where 0 <= percentage && 100 >= percentage, string userName where !string.IsNullOrEmpty(userName) && 20 >= userName.Length && !"Guest".Equals(userName)) { // .... do stuff } |
Really complex validation rules could be separated into its own function or you could always fall back to validation in the body of the method the way we do it now..
2. An ‘IN’ operator
I find the following code a bit redundant:
1 2 3 4 | if (x == 1 || x == 2 || x == 3 || x == 5 || x == 8 || x == 13) { // .... do stuff } |
I’d prefer to borrow the SQL keyword and just write
1 2 3 4 | if (x in (1, 2, 3, 5, 8, 13)) { // .... do stuff } |
EDIT: Apparently SecretGeek already created a class for SQL Style Extensions for C# which does exactly what I wanted (for strings anyway). Thanks Darrel Miller for the link.
3. A 3 way between operator
I’ve always wished we could replace
1 2 3 4 | if (fiscalYearStartDate <= currentDate && currentDate <= fiscalYearEndDate) { // ... do stuff } |
with
1 2 3 4 | if (fiscalYearStartDate <= currentDate <= fiscalYearEndDate) { // ... do stuff } |
4. Only allow var on true anonymous types
var adds awesome functionality to C#, like the ability to create anonymous types from an expression. However, when I start seeing code where all the variables are typed ‘var‘ I get a little worried.
Now I know about type inference and that var is the same at run time as explicitly stating the type, but when you want to look up what the heck variable x is; it’d be nice if the variable definition would tell me
1 | ObjectX v = new ObjectX(); |
instead of
1 | var v = new ObjectX(); |
I also realize, I can figure out the type by looking on the right side of the assignment operator and in the above example above it’s pretty darn clear exactly what type v is. But what if the expression is a method?
1 | var v = DoSomething(); |
Now I’ve got to look up the definition of DoSomething().
Not a big deal, but you’re already 2 definitions away from your core task. This is needless resistance as far as I’m concerned.
Well, you say, I could just use intellisense to hover over the method to get the method’s return type. That is true, because, thank god, the return type for a method (along with parameters) requires the type be specified, so I can get the method type from intellisense with only one definition source code jump. However, this logic is flawed because if the type was used instead of var, intellisense would have told me without any source code definition jumps what the type was. Rather than the useless “(local variable) object v” tip I receive with it.
You know, I am pretty anal about this type of thing, and NO, I haven’t had a real world problems yet, but it just feels wrong.
5. Constant methods and properties
One of the features I always used when I coded in C++ was constant functions. The great thing about constant functions is they prevent side effects. So you know if someone, like yourself, alters functionality which is not expected to change anything, has a side effect, it won’t compile and will have to be dealt with.
This isn’t the most popular functionality in C++ and while this concept helped me write bullet proof code on my own, when I started working on a team, they weren’t very thrilled with the keyword and quickly removed it. But hey, that’s kind of a tell isn’t it?
To be honest, I don’t usually have problems like this with projects I initiate. This may be irrelevant with good design, but I would like the peace of mind in having it anyway.
6. JIT properties without a local variable to cache the value
Remember how you’d need to create a local variable for every property you create? Like:
1 2 3 4 5 6 | private int _id = 0; public int Id { get {return _id;} set {_id = value;} } |
Which became
1 | public int Id { get; set;} |
But what about properties with JIT functionality or have a side effect? Something like this, seems awfully unfair:
1 2 3 4 5 6 | private int _nextId = 0; public int NextId { get {return _nextId++;} set {_nextId = value;} } |
Why not have something like a thisProperty keyword? Something like :
1 2 3 4 5 | public int NextId { get {return thisProperty++;} set; } |
7. Warn command
I’m not talking about the preprocessor #warning. I want something like throw, but without interrupting program flow.
Why? Lets say your data access layer pulls a null or otherwise unexpected value out of a database for a value which should have a very specific set of values.**
This is recoverable and no big deal, you use a default value, but you might like to somehow warn the user this was done. So; you can’t throw an exception since that would interrupt your program flow, I can’t think of any framework component you could add***, you could add some external dependency I suppose, you can build your own external dependency which all future apps will require, you cannot use one of the GUI level features like Session since it wouldn’t be available from the DAL DLL level, and you definitely don’t want to add parameters to every method so you can pass some warning collection up & down the stack!
But something like a warn command looks awfully elegant!
1 | warn new UnexpectedDataWarning("Unexpected status code. Set to 'Open'."); |
Then in the GUI level, you can traverse the warnings collection and display them to the user.
* I can’t figure out which episode it was, so no link. Please comment if you know. Thanks.
** Yes, the database should have constraints, but sometimes things are not under your control or perhaps you have a logical reason to not create constraints … but that’s another post … probably early next week.
*** At least I don’t know of anything. Please let me know if there is something built into core framework which would allow this.
Copyright © John MacIntyre 2010, All rights reserved
WARNING – All source code is written to demonstrate the current concept. It may be unsafe and not exactly optimal.
WRT to your ‘IN’ operator, you can turn it on it’s head:
if (new[] {1, 2, 3, 4}.Contains(x))
{
//Do stuff. The syntax isn’t as nice, but you could write an extension easily enough:
}
public static bool in(this object[] values, object x)
{
return values.Contains(x);
}
Now you’ve got:
if (x.in(new[] {1, 2, 3, 4})
{
}
But that doesn’t seem much better. I guess I would prefer to be able to new up an array without requiring the keyword new[]. Thus: {1, 2, 3, 4} automatically infers the new[] in a similar way var does:
if ({1, 2, 3, 4}.Contains(x))
{
}
or using our extension:
if (x.in({1, 2, 3, 4}))
{
}
WRT to ‘var’. You know you can hold the mouse over the var keyword and it’ll tell you what it is, right?
thus:
var stuff = GetSomeStuff();
where the type is somewhat unintuitive, you can hold your mouse over the ‘var’ keyword and the tooltip will tell you what the type is.
Was thinking you could probably knock up a DXCore plugin to decorate your var statement with an auto comment 🙂
————————————
var stuff = GetSomeStuff(); // Stuff is an ISomeStuff
————————————
It wouldn’t really be there, but you wouldn’t have to type it, it would just show up.
WRT to ‘var’. I find it interesting how many people moan about overuse of the ‘var’ keyword. I use var all over – it promotes better variable naming. In your example
var stuff = GetSomeStuff();
The problem is not the use of ‘var’ – it’s fact that ‘stuff’ and ‘GetSomeStuff’ are not descriptive names! Let’s change it to
IDictionary stuff = GetSomeStuff();
Is that any better? Didn’t think so.
Thanks for the comment Jaco.
I TOTALLY agree with what you said about variable naming. My method name DoSomething() was used so I didn’t have to worry about finding a good example, my own code always has more descriptive naming.
The problem I’m talking about is not the code I write, obviously, I wouldn’t have this problem on my own code, it’s the code others write. And while I can say they shouldn’t have named variable ‘stuff‘, they sometimes do.
I agree with the warn command, that would be a nice feature. It would be useful in cases where currently you’d have a try/finally…
It would be nice if you could handle it in a similar manner to exceptions with a resume keyword perhaps or it just automatically handles Warning types by resuming without requiring a keyword.
try{
//DoStuff…
}
catch(UnexpectedStatusWarning warn)
{
//Report warning;
Resume; //Goes back to the line following the last line of execution
}
Thanks for the comments Ben. That wasn’t really what I meant with the warn command. I more meant, throw it like an exception, but program flow continues like it was never there. Then at you UI level, you can traverse all the warnings thrown throughout your app, and display them to the user. Does that make more sense?
+1 for feature number 6
For parameter validation MS labs has Code Contracts http://msdn.microsoft.com/en-us/devlabs/dd491992.aspx
In regards to warnings, what about Trace.Warn and Debug.Warn?
Thanks for the comment Noah,
I’ve always viewed Trace.Warn() & Debug.Warn() as logging tools. Is there anyway to query the warnings to display to the user while running the application? Let me look that up. That would be nice though.
#1 seems like a huge WTF to me. So you’re basically moving the validation of your parameters from the method body to the argument list? Makes absolutely no sense, and serves to dirty a method’s interface unnecessarily.
Thanks for the comment James,
Parameter constraints isn’t just moving validation from the method body to the argument list, it’s moving it from application code to the language.
And you’re right, it does dirty the parameter list by adding additional information, but aren’t the parameter constraints as important as the parameters themselves? In my opinion it’s vital information, which can be easily glossed over when in the body of the code.
Hi John,
For issue #1, it’s not in the language, but you should have a look at Code Contracts in .NET 4 if you haven’t already.
chris