If you could make breaking changes to C#, what would you do?
-
@lucas1 said in If you could make breaking changes to C#, what would you do?:
@dkf I would fuck you with a rusty rake if that happened. Honestly it is a language that is normally done with an IDE so you know whether the conditional is valid in the context of the method.
And you'll goto fail because of it.
-
@blakeyrat said in If you could make breaking changes to C#, what would you do?:
In that case, and only that case, you can do this
TIL, huh. I guess it just mirrors the variable declaration syntax? You can do:
int a = 10, b = 20, c = 30, d = 40;
But not
int a = 10, b = 20, c = 30, short d = 40;
In the declaration it's just a matter of replacing the comma with a semicolon, with the
using
it requires a whole new statement. So I'd wager the reason was to be able to just parse what's in the using statement exactly the same as a variable declaration.
-
@blakeyrat said in If you could make breaking changes to C#, what would you do?:
That only works because the two types your creating inside the
using
are the same type. It would be nice if C# supported doing that with different types, although I'm sure there's some good reason it doesn't.The equivalent in Java supports multiple types, so there's no fundamental semantic reason for the restriction. It's just a syntax thing.
-
@dkf Yeah. It's always kind of bugged me. They actually wrote a specific compiler error that reads, "using statements can't contain more than one type" or something like that. In the time it took them to detect and report that error, you'd think they could have just fixed the issue so they worked in the expected way.
-
@maciejasjmj said in If you could make breaking changes to C#, what would you do?:
@coldandtired said in If you could make breaking changes to C#, what would you do?:
@jbert Yes. As it is, you add the line just to keep the compiler happy.
You still need
break
to disambiguate betweencase 1: case 2: stuff()
and
case 1: break; case 2: stuff()
In fact this case gets really confusing when
break
is otherwise omitted, since the former example looks like it would do nothing for case 1.What C does that C# does not is something like this:
case 1: perform1stuff(); break; case 2: perform2stuff(); /* I think C# will complain here about not having a break...? */ case 3: perform2and3stuff(); /* C# will not execute this for 2, but C will. */ break; case 4: case 5: /* C# and C both fall through here. */ perform4_5stuff(); break;
I think this sort of fall-through can be very useful, and it provides a real use for
break;
.
-
@masonwheeler said in If you could make breaking changes to C#, what would you do?:
@maciejasjmj said in If you could make breaking changes to C#, what would you do?:
What if you want to take the enumerable as a constructor parameter?
Then the class would have a generic
<T>
and the constructor would take anIEnumerable<T>
.Then I'd say you're leaking abstraction, since new-ing up the class requires the user to know what the T is. Despite the whole idea being that counting should not depend on that.
-
@djls45 It already does it.
case 1: case 2: doStuff(); default: doOtherStuff();
-
I think that's not possible without defining how would you handle the case when there is no default constructor to the class? (Explicitly having private constructor, or being an abstract class type)
On the other hand, making all value types nullable by default is doable, but I don't want that either.
-
@dreikin said in If you could make breaking changes to C#, what would you do?:
@pleegwat said in If you could make breaking changes to C#, what would you do?:
@maciejasjmj said in If you could make breaking changes to C#, what would you do?:
@coldandtired said in If you could make breaking changes to C#, what would you do?:
@jbert Yes. As it is, you add the line just to keep the compiler happy.
You still need
break
to disambiguate betweencase 1: case 2: stuff()
and
case 1: break; case 2: stuff()
In fact this case gets really confusing when
break
is otherwise omitted, since the former example looks like it would do nothing for case 1.If we're reinventing syntax, then how about:
case 1, 2 { stuff() }
and
case 1 { } case 2 { stuff() }
Why add the braces? Just do
case 1, 2: stuff();
Hello, I see you're trying to invent Go. Let me help you with that:
switch foo { case 1, 2: stuff() }
-
@raceprouk said in If you could make breaking changes to C#, what would you do?:
@jbert said in If you could make breaking changes to C#, what would you do?:
- Make more explicit that
throw e
resets an exception's stacktrace.
I'd favour something a bit different:
throw;
andthrow e;
preserve the stack tracethrow e with reset;
resets the stack trace
What about this:
throw e
simply passes the exception on up the stack without resetting it.rethrow e
resets the stack, but passes the same exception along.throw new exception()
resets the stack and creates a new exception.rethrow new exception()
does the same asthrow new exception()
.
???
- Make more explicit that
-
@ben_lubar said in If you could make breaking changes to C#, what would you do?:
Hello, I see you're trying to invent Go.
It didn't work the first time, so why not try again...
-
@ben_lubar We already have something that is fine as I have previously point out.
-
@dkf said in If you could make breaking changes to C#, what would you do?:
Breaking changes? I suggest disallowing the form:
if (xyz) thing.Do_Something();
and forcing the braces to be provided:
if (xyz) { thing.Do_Something(); }
It makes things one heck of a lot easier for maintenance programmers. (Similarly for other control constructs.)
If that's too much to stomach, go the other way and allow
try
andusing
to not be braced if you're only putting a single statement inside.Hello, I see you are also trying to invent Go.
if xyz { thing.Do_Something() }
-
@djls45 That would be good. But one has a stack trace normally.
-
Why would anyone ever want to reset the stack trace? You might as well do this instead:
try { somethingWhichDefinitelyBarfsAtYou(); } catch(SomeException sex) { throw new SuperGenericAndUtterlyPointlessException(sex.Message); }
-
Can we talk about racism instead as that is probably a less contentious issue ;-)
-
@alexmedia said in If you could make breaking changes to C#, what would you do?:
Why would anyone ever want to reset the stack trace? You might as well do this instead:
try { somethingWhichDefinitelyBarfsAtYou(); } catch(SomeException sex) { throw new SuperGenericAndUtterlyPointlessException(sex.Message); }
throw new Exception(ex.GetType().Name.Substring(0, 1));
-
@ben_lubar Get fucked.
-
@djls45 said in If you could make breaking changes to C#, what would you do?:
What about this:
throw e
simply passes the exception on up the stack without resetting it.rethrow e
resets the stack, but passes the same exception along.throw new exception()
resets the stack and creates a new exception.rethrow new exception()
does the same asthrow new exception()
.
???
That syntax is miles better than mine
@alexmedia said in If you could make breaking changes to C#, what would you do?:
Why would anyone ever want to reset the stack trace?
To hide inner implementation details in a library. Not the best excuse, but the only one I can think of.
@alexmedia said in If you could make breaking changes to C#, what would you do?:
sex.Message
-
@maciejasjmj said in If you could make breaking changes to C#, what would you do?:
@coldandtired said in If you could make breaking changes to C#, what would you do?:
the first case is supposed to do nothing then it's only included to keep the compiler happy, unless you have a situation where you want some cases to do something, some to do nothing, and some to do whatever the default is. Is this common?
If you're switching on an enum, I'd say you usually want to include all enum values even if for some of them you don't do anything. And without
break
you have no way to represent an empty switch case, and if you try to, it causes a fallthrough instead, which isn't consistent.What could be done is to put all the empty cases at the end so they all fall through to nothing.
-
@djls45 said in If you could make breaking changes to C#, what would you do?:
@raceprouk said in If you could make breaking changes to C#, what would you do?:
@jbert said in If you could make breaking changes to C#, what would you do?:
- Make more explicit that
throw e
resets an exception's stacktrace.
I'd favour something a bit different:
throw;
andthrow e;
preserve the stack tracethrow e with reset;
resets the stack trace
What about this:
throw e
simply passes the exception on up the stack without resetting it.rethrow e
resets the stack, but passes the same exception along.throw new exception()
resets the stack and creates a new exception.rethrow new exception()
does the same asthrow new exception()
.
???
Why would you even reset an exception stack in the first place instead of newing one up and including the previous one as an InnerException? That's literally what it's for.
- Make more explicit that
-
@djls45 It does that anyway. Do you do C#?
-
@raceprouk said in If you could make breaking changes to C#, what would you do?:
To hide inner implementation details in a library. Not the best excuse, but the only one I can think of.
If you want to hide inner implementation details, use an obfuscator. Of course stack traces shouldn't be printed to the end user, they should just be
silently swallowedlogged in a monitoring tool.
-
Make DateTime type use UTC by default, and need .ToLocal() to get local datetime.
This let us to get rid of all the troubles introduced by daylight saving time, and the conversion errors produced by need to convert DST-ed local time back to UTC.
-
@alexmedia The evil web programming security stuff comes to the surface :D
-
Speaking of
switch
:Syntax to tell C# "I'm switching on an
enum
, if a new value is added to theenum
definition throw a syntax error at build time".enum People { Bob, Ted }; var peeps = People.Bob; switch( peeps as all People ) // No idea what this syntax would look like { case Bob: blah(); break; } // Syntax error: "not all values of enum People represented inside switch statement"
-
@djls45 said in If you could make breaking changes to C#, what would you do?:
case 1: perform1stuff(); break; case 2: perform2stuff(); /* I think C# will complain here about not having a break...? */ case 3: perform2and3stuff(); /* C# will not execute this for 2, but C will. */ break; case 4: case 5: /* C# and C both fall through here. */ perform4_5stuff(); break;
C# will do exactly what your example shows without any breaks at all (or rather, it could but instead complains about the missing breaks).
The only use I see for it is something like
switch (Colour) { case RED: DoStuff(); break; case ORANGE: break; // Fuck orange case YELLOW: case GREEN: DoOtherStuff(); break; default: DoSomethingElse(); break; }
Where there is a do-nothing choice as well as a default choice, but I wonder how common or how recommended that is.
-
@raceprouk said in If you could make breaking changes to C#, what would you do?:
To hide inner implementation details in a library.
So you want the exception message, type, data and everything to bubble up to the user, but the stack trace is secret? Why?
If you're not throwing library-specific exceptions then it's already an unhandled exception in the library, so why would you deprive yourself of a useful bug report?
-
@blakeyrat said in If you could make breaking changes to C#, what would you do?:
Speaking of
switch
:Syntax to tell C# "I'm switching on an
enum
, if a new value is added to theenum
definition throw a syntax error at build time".enum People { Bob, Ted }; switch( all People ) { case Bob: blah(); break; } // Syntax error: "not all values of enum People represented inside switch statement"
I'll add "... unless FlagAttribute is specified" because if that's flag enum, it's perfectly acceptable to have value that's not explicitly defined.
-
@maciejasjmj May I direct your attention to the sentence immediately following the one you quoted:
@raceprouk said in If you could make breaking changes to C#, what would you do?:
Not the best excuse, but the only one I can think of.
-
@coldandtired Already said that. LOL
-
@cheong Right.
Right now you can do the:
default: throw new ArgumentOutOfRangeException( "Enum!" );
But the problem is, while that's a handy check, it'll only fire off at run time. You really want the build to fail if all possible
enum
values aren't considered in theswitch
.
-
@blakeyrat they are ints so I don't think that is possible.
-
@maciejasjmj said in If you could make breaking changes to C#, what would you do?:
Then I'd say you're leaking abstraction, since new-ing up the class requires the user to know what the T is. Despite the whole idea being that counting should not depend on that.
Then that's the real change you want in C#: allow type inference on
new
calls. :P
-
@masonwheeler I use something to getInstance on a lot of classes.
var someClass = Class.GetInstance()
as a factory method.
-
@lucas1 said in If you could make breaking changes to C#, what would you do?:
@djls45 It already does it.
case 1: case 2: doStuff(); default: doOtherStuff();
C# does that? Does it allow that with other cases than
default
?
-
@djls45 yes if you define them. Thus Enums.
-
What about forcing package names to reflect the folder structure? My current job takes full advantage of this lack of requirement and it pisses me off.
-
@lucas1 said in If you could make breaking changes to C#, what would you do?:
@djls45 It does that anyway. Do you do C#?
I was just pointing out the logical construction if someone wanted to explicitly list all the values for an enum, but some of them did not have code to run.
I was agreeing with you that it is a logic problem, not a language or syntax problem.
-
@djls45 Fair enough. I was just talking about C# I have been doing it close to 10 years now.
-
@dkf Sounds like maintenance programmers who don't know C#, and why would you hire those to maintain C# code?
-
@the_quiet_one said in If you could make breaking changes to C#, what would you do?:
What about forcing package names to reflect the folder structure? My current job takes full advantage of this lack of requirement and it pisses me off.
I think you mean "namespace"?
Yeah that'll be great. How about just make "namespace" statement do nothing and auto assigning sub-namespace corresponding to folder structure? I'd be happy to see it goes that way.
And not necessary breaking change at all if we can introduce a project properties that enables this behavior (i.e.: only for this project) so the cleanup could be done one-by-one.
-
@coldandtired said in If you could make breaking changes to C#, what would you do?:
@djls45 said in If you could make breaking changes to C#, what would you do?:
case 1: perform1stuff(); break; case 2: perform2stuff(); /* I think C# will complain here about not having a break...? */ case 3: perform2and3stuff(); /* C# will not execute this for 2, but C will. */ break; case 4: case 5: /* C# and C both fall through here. */ perform4_5stuff(); break;
C# will do exactly what your example shows without any breaks at all (or rather, it could but instead complains about the missing breaks).
The only use I see for it is something like
switch (Colour) { case RED: DoStuff(); break; case ORANGE: break; // Fuck orange case YELLOW: case GREEN: DoOtherStuff(); break; default: DoSomethingElse(); break; }
Where there is a do-nothing choice as well as a default choice, but I wonder how common or how recommended that is.
I think you missed this part:
case 2: perform2stuff(); /* I think C# will complain here about not having a break...? */ case 3: perform2and3stuff(); /* C# will not execute this for 2, but C will. */ break;
The handling for
2
is split across both, because3
also shares part of the handling for2
.
-
@cheong said in If you could make breaking changes to C#, what would you do?:
@the_quiet_one said in If you could make breaking changes to C#, what would you do?:
What about forcing package names to reflect the folder structure? My current job takes full advantage of this lack of requirement and it pisses me off.
I think you mean "namespace"?
Yes. I've been on vacation all week, so certain parts of my brain are temporarily archived and strangely replaced with java which I haven't done in 15 years
-
@cheong No.
Making namespaces follow directory structure is stupid anyway, and an awful default.
When you're calling things, you don't want to have 10 different usings for three different classes. You need an exception? Most of them are just in
System
.Large, flat namespaces are legitimately useful, while namespaces on a granular level only help if your architecture is over-engineered and repetitive.
-
@magus I wouldn't quite take it that far, but I'll say that as a general rule, the more dots there are in your namespaces, the worse they smell.
-
@djls45 said in If you could make breaking changes to C#, what would you do?:
I think you missed this part:
case 2: perform2stuff(); /* I think C# will complain here about not having a break...? */ case 3: perform2and3stuff(); /* C# will not execute this for 2, but C will. */ break;
The handling for 2 is split across both, because 3 also shares part of the handling for 2.
C# won't let you do it. So the compiler knows what it has to do but makes you add the break anyway.
-
@djls45 said in If you could make breaking changes to C#, what would you do?:
@coldandtired said in If you could make breaking changes to C#, what would you do?:
@djls45 said in If you could make breaking changes to C#, what would you do?:
case 1: perform1stuff(); break; case 2: perform2stuff(); /* I think C# will complain here about not having a break...? */ case 3: perform2and3stuff(); /* C# will not execute this for 2, but C will. */ break; case 4: case 5: /* C# and C both fall through here. */ perform4_5stuff(); break;
C# will do exactly what your example shows without any breaks at all (or rather, it could but instead complains about the missing breaks).
The only use I see for it is something like
switch (Colour) { case RED: DoStuff(); break; case ORANGE: break; // Fuck orange case YELLOW: case GREEN: DoOtherStuff(); break; default: DoSomethingElse(); break; }
Where there is a do-nothing choice as well as a default choice, but I wonder how common or how recommended that is.
I think you missed this part:
case 2: perform2stuff(); /* I think C# will complain here about not having a break...? */ case 3: perform2and3stuff(); /* C# will not execute this for 2, but C will. */ break;
The handling for
2
is split across both, because3
also shares part of the handling for2
.It could be done if continue statement could be extended to be used in here.
-
@magus how about this:
Have folders which serve to organize your code the way you want without changing your namespace and have "namespace" folders which do.
Only thing I don't like about that is it would have to add metadata to the csproj file to make sense of it all.
-
@coldandtired said in If you could make breaking changes to C#, what would you do?:
@djls45 said in If you could make breaking changes to C#, what would you do?:
I think you missed this part:
case 2: perform2stuff(); /* I think C# will complain here about not having a break...? */ case 3: perform2and3stuff(); /* C# will not execute this for 2, but C will. */ break;
The handling for 2 is split across both, because 3 also shares part of the handling for 2.
C# won't let you do it. So the compiler knows what it has to do but makes you add the break anyway.
That's what I'm saying. I want the fall-through right here, but C# doesn't allow it.