Earlier, you mentioned F#. How easy is it to combine C# and F#?
https://docs.microsoft.com/en-us/dotnet/standard/language-in...
That details the C# point of view (a little VB too) and here's an SO post on how to add the CLSCompliant attribute to F#:
https://stackoverflow.com/questions/21028833/writing-cls-com...
I remember these concepts being very important in the early days of .NET because companies had heavy investments in legacy code, including COM, C, C++, other .NET languages (various forms of interop) and needed integration and/or upgrade migration paths. Language interop came into play because some companies thought (not taking an opinion here) it might be a good idea for developers to use the language of their choice.
(I've not actually done it myself, writing functional-style C# is enough for me)
- typechecked, but the types get out of the way; "var" and intellisense fill them in for you. It also shows you what types the function arguments should be and autosuggests objects of those types
- functional when you want, but not when you don't: LINQ et al, interlinkage with F# if you want to get really functional, now immutable record types. Lambdas.
- wordy enough that you can see context, but Intellisense means not having to type it out
- smart refactoring (paid-for Resharper)
- debugger when you need it: run test case. Wait to hit exception or breakpoint on failed assertion. Inspect values. It's often immediately obvious where the problem was.
- CPU and memory profilers readily available and well integrated.
- standardised on Nunit with Nsubstitute for testing: bit wordy, but with a bit of thought we're now hitting 100% line coverage on wholly new code.
- portable ish binaries with Mono
- package management system is mature. (Wart: packages are at the "project" rather than "solution" level in VS, so you need to do extra work to ensure they're all the same version)
The only real downside is the build system (MSBuild) is pretty poor, badly documented, and not easy to use for other things than C#.
For the future? "Software components" have never quite delivered. Package management is clearly the frontier here.
Language interoperability is another: it's still astonishingly hard to combine languages within a single software artefact unless they're C and C++ or similar things that produce platform-native binaries. Proliferation of language runtimes makes this worse, not better. On the other hand, the two frontrunner runtimes of C# and Java both have problematic owners.