[HN Gopher] Welcome to C# 10
       ___________________________________________________________________
        
       Welcome to C# 10
        
       Author : tonicbbleking
       Score  : 65 points
       Date   : 2021-11-08 17:12 UTC (5 hours ago)
        
 (HTM) web link (devblogs.microsoft.com)
 (TXT) w3m dump (devblogs.microsoft.com)
        
       | sbelskie wrote:
       | The most interesting feature here (though included only as a
       | preview) is static abstract members on interfaces, which will
       | make things like generic math possible.
        
       | t-writescode wrote:
       | Oh wow. I do _not_ like that  "global using". It harkens to the
       | auto-loading issues I've had with Rails. "Where was this defined?
       | I dunno! It probably works here, though!!1"
       | 
       | I generally don't like a random file impacting several other
       | files. Extension methods are ... tolerated and ... "fine" but I
       | still feel unpleasant using them.
       | 
       | File-Scoped namespaces seem like someone's really, really tired
       | of having nested folders and seems actively unnecessary.
       | 
       | I like natural lambda types
       | 
       | Good update on parameterless structs. I assumed that's how they
       | worked already. I haven't used C# in 2 years; but you could do
       | that with classes back when, so I assumed it would be the same
       | with structs.
       | 
       | Constant interpolated strings is nice.
       | 
       | Extended property patterns is fine, just probably not for me.
        
         | HideousKojima wrote:
         | Doesn't really bother me, so long as the global usings are only
         | kept to a single file. Intellisense will tell you the full
         | namespace, then you can just see if you've got that namespace
         | in the file you're in or in your dedicated global usings file.
        
           | jdmichal wrote:
           | I thought it was generally considered good practice to put
           | extension methods into static classes in their own file. So
           | like `FooExtensions.cs` if you are writing extensions for the
           | `Foo` class.
           | 
           | I would consider this the same: Project should have a
           | `GlobalUsings.cs` file.
           | 
           | Does C# have any linters available that could enforce such a
           | conventions?
        
             | int_19h wrote:
             | C# has a framework in-place to facilitate workspace-
             | specific linters, so even if one doesn't exist, it could be
             | written very easily (and premade ones are sure to appear
             | quickly).
             | 
             | https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-
             | sdk/tu...
        
           | t-writescode wrote:
           | > so long as the global usings are only kept to a single file
           | 
           | Here's where the mess starts.
           | 
           | It seems far too easy to sneak a global import statement in
           | to random files and then have the entire codebase polluted by
           | it.
           | 
           | I feel like this is too foot-gun'y, myself.
        
         | amir734jj wrote:
         | I do not like that "global using" as well. I wonder why they
         | added it.
        
           | orthoxerox wrote:
           | Because most files in C# start with:
           | 
           | using System; using System.Collections.Generic;
           | 
           | and a few more lines like that. Think of this part of the BCL
           | as the prelude in Haskell.
        
           | Someone1234 wrote:
           | Looks like they added global usings to support their implicit
           | usings functionality. Essentially they want to save people
           | having to put using System, System.Linq,
           | System.Collections.Generic, and others[0] at the top of
           | nearly _every_ C# file.
           | 
           | I'm of two minds:
           | 
           | - I think they're an anti-pattern, because it creates a
           | global scope that can get messy/annoying.
           | 
           | - It makes a ton of sense for the implicit usings
           | functionality, and I'm tired of needing to add the basic SDK
           | usings to every source file.
           | 
           | So the ideal is to enable .Net's implicit usings, then to use
           | an analyzer to "ban" adding more global usings directly from
           | your solution/project. Best of both worlds that way.
           | Alternatively just make them a no-pass item for code reviews.
           | 
           | [0] https://docs.microsoft.com/en-
           | us/dotnet/core/compatibility/s...
        
             | AlfeG wrote:
             | > Essentially they want to save people having to put using
             | System, System.Linq, System.Collections.Generic, and
             | others[0] at the top of nearly every C# file.
             | 
             | Interesting that this doesn't bother me at starting from
             | .net 1.0. All tools (including raw VS without addins) can
             | add those using automatically and they do.
             | 
             | But for me it's still a nice to have feature if VS will be
             | able to show where this using is defined.
        
             | sbelskie wrote:
             | This is what I've settled on. Implicit usings for the SDK
             | are great but otherwise I don't want this in any code base
             | I work on.
        
             | metaltyphoon wrote:
             | It's literally the same as Rust's prelude system and I
             | don't see anyone complaining so much about this.
        
           | slownews45 wrote:
           | It's an easy way to do a config without a full importer and
           | complexity in passing config around / looking it up.
           | 
           | I like it. This goes way back. They give the example of a
           | globalusings file.
           | 
           | That's a cheap / easy way to do a config file (at least one
           | use case).
        
         | int_19h wrote:
         | To be fair, global usings aren't fundamentally different from
         | assembly references (which have always been per-compilation
         | rather than per-file).
         | 
         | With respect to parameterless struct constructors: the reason
         | why C# didn't have that historically is because there are many
         | corner cases where those aren't invoked in CLR. Basically any
         | place where you can't do "new" directly on the struct itself -
         | e.g. when you create an array of structs, its elements do _not_
         | have the constructor run for them. So C# designers originally
         | decided that it would be less confusing overall if structs were
         | always default-init, in all contexts - which means no
         | parameterless constructors. I 'm not sure what prompted the
         | change of mind.
        
         | negativegate wrote:
         | File-scoped namespaces is nice to not have every class already
         | sitting at one level of indentation. I don't see what it has to
         | do with nested folders.
        
         | david_allison wrote:
         | > Oh wow. I do not like that "global using". It harkens to the
         | auto-loading issues I've had with Rails. "Where was this
         | defined? I dunno! It probably works here, though!!1"
         | 
         | It's been a feature of Visual Basic .NET for a very long time
         | (from recall: at least 2008), I'd hope Microsoft heavily
         | queried user feedback before implementing.
         | 
         | https://docs.microsoft.com/en-us/visualstudio/ide/how-to-add...
        
       | yread wrote:
       | I like it. Nothing too crazy (well except maybe the return types
       | and attributes on lambdas that could make some ugly code), mostly
       | quality of life improvements and stuff you expected to work in C#
       | 9.
        
       | pharmakom wrote:
       | C# is becoming the C++ of managed languages. I wish they would
       | stick to a smaller set of more powerful features... like an
       | earlier C# with hygienic macros or something.
        
         | bmitc wrote:
         | > I wish they would stick to a smaller set of more powerful
         | features
         | 
         | That's basically F#. One can program just using OOP in F#, and
         | it is much more clean and concise.
        
         | cogman10 wrote:
         | Does that make Java the C of managed languages?
         | 
         | The great thing about C#/kotlin throwing the kitchen sink at
         | stuff is the good stuff eventually makes it's way into Java.
        
           | pharmakom wrote:
           | (For me at least) life is too short to wait for the best
           | features to trickle down. I mean, most of the interesting
           | Java 17 stuff was surpassed by OCaml in 1995! That's a 35
           | year lag!
        
           | azth wrote:
           | I find Java's features to be very well balanced, and only
           | make it into the language after they've been vetted and
           | tested in the wild by other languages.
           | 
           | e.g. see their take on concurrency by means of project Loom.
           | No need for async/await and providing separate APIs for sync
           | vs async operations. It has records and sealed types and
           | pattern matching, and is getting destructuring soon.
        
             | int_19h wrote:
             | .NET async interops nicely with any other language that can
             | do basic callbacks (even C!). How does that work in Loom?
        
               | rvcdbn wrote:
               | Definitely not as easy but Go managed to get it to work
               | fairly well with some extra overhead. I would rather the
               | language design for pure Java first and C interop second.
        
               | int_19h wrote:
               | This approach results in more closed ecosystems, though,
               | where everything has to be re-implemented to work well,
               | instead of reusing existing libraries (that have been
               | polished for decades in some cases).
               | 
               | Also, what about OS APIs? Those always going to be at the
               | bottom of the stack, and they are increasingly async
               | themselves.
        
               | cogman10 wrote:
               | For VM languages no problem, all those languages will
               | support threads or using threads.
               | 
               | For non-VM interopt it will block the carrier thread if a
               | native call causes any sort of blocking.
               | 
               | In Java, external to the VM calls are almost non-existent
               | so it's not much of an issue. Likely you'd do those sorts
               | of calls as regular kernel threads instead of the Loom
               | virtual threads.
        
               | int_19h wrote:
               | To clarify, by interop here I don't just mean calling
               | foreign functions. I mean calling _async_ foreign
               | functions. When async is explicit, it 's easy to handle
               | it on ABI level - it's just a bunch of callbacks (or
               | abstractions wrapping them, like tasks/futures).
               | 
               | For example, suppose you're writing a Windows desktop
               | app, and you decide to do so in Java. Modern Windows APIs
               | are async. How would you asynchronously invoke such an
               | API? In C#, you'd just use await.
        
             | pharmakom wrote:
             | I much prefer the Haskell / F# approach of using do-
             | notation to allow the user to build their own syntax.
             | 
             | I don't think I can build an Async<Either<E, T>> expression
             | with Loom, for example.
        
         | metaltyphoon wrote:
         | I agree in a sense but I would do it another way. Either change
         | to the Rust edition equivalent, or simply drop old stuff and
         | keep in the newer bits.
        
         | Someone1234 wrote:
         | They really need to start marking stuff with [Obsolete()] more
         | aggressively. C# has some now outmoded data structures and even
         | keywords.
         | 
         | I'd love to see a C#/.Net Standard release that was dedicated
         | to getting rid of things. It may be less exciting in the short
         | term, but it is well past due.
        
       | quotemstr wrote:
       | Ugh. So with the new method groups feature, adding a new method
       | overload can break working code even if that code never calls the
       | new overload.
        
         | nick_ wrote:
         | Changing the code changes the code.
         | 
         | In any popular language, if you have some method whose single
         | argument is being implicitly upcast by a caller then you add a
         | more specific overload on that arguments inheritance hierarchy,
         | the caller will now be calling the new method.
        
         | moron4hire wrote:
         | That was already the case. This does not change that issue.
         | 
         | Using the example of Console.Read from the article, in C# 9,
         | you could do `Func<int> read = Console.Read;`. Now, if someone
         | adds an overload for the Read method to Console, that C# 9 code
         | will break.
         | 
         | In C# 10, that doesn't change. What changes is that we don't
         | have to specify `Func<int>`. We can just use `var`.
        
           | int_19h wrote:
           | You wouldn't even have to get lambdas involved for this
           | problem to surface. Consider something like this:
           | void Foo(double x) { ... }             Foo(123);
           | 
           | This works, but now I add an overload:                  void
           | Foo(decimal x) { ... }
           | 
           | and the above call is now ambiguous. Note that this example
           | goes all the way back to C# 1.0!
           | 
           | Method overloading (and how it interacts with other language
           | features) is probably the single most complicated part of C#
           | today, for good reasons.
        
           | nick_ wrote:
           | That's right. Additionally, this worked back to C# 4 or 5, I
           | think?
        
       | alberth wrote:
       | Dumb questions: why does it seem like languages always
       | continually add features?
       | 
       | Can a language not become "feature complete", while still
       | improving over time?
        
         | bmitc wrote:
         | I think F#, Clojure, and Elixir are languages that show it's
         | possible to stop adding major features to.
        
           | Jtsummers wrote:
           | Scheme as well. Notably, these languages are (mostly) capable
           | of letting developers add new models of computing or software
           | design on top of the base language in a way that appears
           | natural as a user.
           | 
           | If you want OO in Scheme, you can do it (and various models
           | of OO at that). If you want a concurrent model, you can do
           | it. If you want a relational programming model, you can have
           | it.
           | 
           | Try doing the same with, for example, C. You can accomplish
           | it, but you have to jump through hoops or rely on OS
           | libraries or other things. And it will rarely, if ever, feel
           | "natural" within the language.
        
         | xonix wrote:
         | There is Awk - fascinating mini-language almost unchanged for
         | decades. Therefore very portable. You can learn it once and be
         | sure you know it all.
        
         | Verdex wrote:
         | We don't know how to make languages. We're in the Kepler stage
         | of software development. Everyone has a different 'cosmology'
         | to explain what's going on, we don't yet have the technology to
         | understand what's going on, we don't have the math yet to
         | explain what's going on, and we're just in the very beginning
         | stages of even being able to take measurements of anything
         | worth while.
         | 
         | "Here's a feature" Now, will it makes code bases better? Will
         | it make them worse? Do we even have a way to quantify better or
         | worse?
         | 
         | What looks like is happening to me is that general purpose
         | languages are all slowly migrating to look a lot like ML with
         | some sort of existential mechanism. So that is static type
         | system with generics, lambdas, algebraic data types, pattern
         | matching. The existential part is typically expressed with
         | interfaces, but it looks like there's a few options floating
         | around.
         | 
         | Meanwhile, low level programming language designers are all
         | going crazy trying to find a way to replace c / c++. Rust,
         | Odin, Zig, Jai (if it ever actually gets released), etc. That
         | probably won't look like ML or at least it will need to have
         | some other stuff to handle the domain without driving
         | developers crazy.
         | 
         | I'm sure other domains will slowly figure out that they can
         | cheat the triumvirate of engineering (fast, cheap, good) by
         | developing languages that suit their domain.
         | 
         | But I suspect we're looking at 50-100 years before we really
         | start to see any progress that lets us have "feature complete"
         | languages.
        
           | alberth wrote:
           | I wonder if there is any parallels of programming languages
           | to spoken languages.
           | 
           | Every year, new words are constantly added to official
           | dictionaries ... while old words continually fall out of
           | favor/use.
           | 
           | And concepts in one language (e.g. "English" or "Rust") then
           | get adopted/imported into another language (e.g. "French" or
           | "Go").
        
             | jdmichal wrote:
             | There's also domain-specific language / slang.
             | 
             | I think this analogy is a good one. I've always held that
             | software development has a crafty side in addition to the
             | raw computer science. And I think you nailed it that this
             | is where that comes in. There's multiple ways to write any
             | program. So the only "complete" language is one that allows
             | you to express anything and everything exactly the way you
             | want to.
             | 
             | For instance, one could argue that using process forking vs
             | threads vs fibers vs async / await are all just different
             | connotations of the same denotation of "doing multiple
             | things in parallel".
        
             | int_19h wrote:
             | Words in natural language dictionaries is more akin to
             | functions in libraries. OTOH natural language _syntax_
             | doesn 't change nearly as fast.
             | 
             | But OP is right - we haven't really been doing programming
             | all that long in the grand scheme of things, and there are
             | still too many unsettled questions.
             | 
             | Also, in many cases, we came up with desirable concepts
             | long ago, but using them wasn't feasible due to performance
             | overhead until recently.
        
       | Erlangen wrote:
       | Is "natural types" a common term used in programming language
       | theory? I haven't heard of it before. I tried to search it but
       | found nothing.
        
       | breakingcups wrote:
       | Not all of these changes sound good to me. Some sound like very
       | niche cases that I now have to make a decision about when it
       | comes to coding guidelines because there's always going to be
       | that one developer in our company who wants to show off, even if
       | it's not the right tool for the job.
        
       ___________________________________________________________________
       (page generated 2021-11-08 23:02 UTC)