Hacker News new | past | comments | ask | show | jobs | submit login
.NET 5.0 – New APIs (ndepend.com)
172 points by todsacerdoti on Sept 22, 2020 | hide | past | favorite | 142 comments



I was kinda looking at migrating my project over to .NET Core/.NET 5 lately... turns out that despite bringing over Windows Forms and WPF support, Microsoft refuses to port System.Speech for text-to-speech and speech recognition.

Turns out the reason why is that since the Speech team moved under Azure, the Speech team considers System.Speech "replaced" by Azure's cloud-based speech services. Kinda takes any idea I had of moving to Microsoft's modern platform off the table for me, because local-only functionality is a must-have in my book. And there's no reason my Windows machine shouldn't be able to do the same local-based speech capability PCs have had for the past couple decades without the cloud.


> Microsoft refuses to port System.Speech for text-to-speech and speech recognition.

I think it's more complicated than just 'porting'... Something tells me that System.Speech is a nice wrapper for a very windows specific API. Similar to how Microsoft isn't bringing over WCF Hosting (Because too many parts of it are dependent on Windows itself.)

Now, ideally, it would be nice if Microsoft would expose the existing System.Speech source code, so that somebody could begin the efforts of making it into an OSS Project that could eventually become multiplatform.


Windows Forms and WPF are also both Windows API wrappers, and they've been brought over for when you are targeting Windows-based platforms.

System.Speech is no longer available on Windows in .NET 5, even if you're using Windows Forms or WPF, which are Windows-only frameworks.

In theory, if Microsoft was at least holding up compatibility for such things on Windows, I could move my target towards .NET Core/.NET 5, then gradually replace Windows-specific code with cross-platform code. But as per usual, I'm getting the impression it'd be easier to start over than migrate.

I agree it'd be really nice if they open sourced the code necessary to look at porting System.Speech, but I imagine it'd be unpleasant as a business decision: It'd erode their ability to bill people for the Azure "replacement".


.NET Core/Standard already has windows specific API's, and .NET 5 is going to make them safer to use going forward with static analysis[0], so I doubt the Windows specificness is the reason why.

0: https://devblogs.microsoft.com/dotnet/the-future-of-net-stan...


Being windows dependent shouldn't prevent offering System.Speech as a library that targets only windows.


It’s possible that that System.Speech is using technology and patents licensed to Microsoft for use in Windows but not something they can sub-license.


They could treat it like the UI stuff and make it windows only but still in Core 5. But there are other things that aren't getting ported forward for various reasons like WCF.


I hope MS to release closed sourced windows-only library port even in such situation.


I consider this the most likely explanation.


Isn't there a WinRT API that you can use from .net 5?


Plausible, though https://docs.microsoft.com/en-us/uwp/api/windows.media.speec... looks significantly simplified from https://docs.microsoft.com/en-us/dotnet/api/system.speech.sy...

I'm not confident all the same functionality I've tapped into can be replicated with this.


As WinRT fanboy, I must admit that with Project Reunion, everything UWP related in now in a chaotic state without any clear roadmap on how everything will move forward, just high level ideas.

So I wouldn't bet in anything WinRT related for the time being.


no third party libraries that fit the bill?


I investigated a little bit, but most of the speech libraries on NuGet are either wrappers for Google/Microsoft/Amazon/IBM cloud services, or are dependent on System.Speech anyways.

It's plausible if I really wanted to, I could run a separate service/application from some non-.NET-based alternative, but the integration is likely to be a lot messier. Right now, I'm not sure .NET 5 offers a compelling reason to drop .NET Framework, which Microsoft will presumably continue to support for at least the next decade.

Microsoft still lacks a cross-platform desktop UI framework, they have no project template in Visual Studio that would let you write a service that can run as a service on both Windows and Linux, and .NET 5 is missing lots of Windows integration functionality like System.Speech as well. I'd really like to make my project both run as a service, and run cross-platform, but there doesn't appear to be a good path to do either one with .NET 5 yet, and it'd likely take substantial rewriting just to get my project to .NET 5 on Windows.


> they have no project template in Visual Studio that would let you write a service that can run as a service on both Windows and Linux

I have lots of complaints about the state of the .NET ecosystem, but thankfully this one is pretty easy IMO. Basically just use the `dotnet new worker` .NET Core template; it scaffolds a project using the ASP.NET Core generic host, which can easily (a NuGet package and 1 line of code) be adapted to run as either a Windows Service or a systemd service on Linux.

https://www.hanselman.com/blog/dotnetNewWorkerWindowsService... https://www.reillywood.com/blog/dotnet-linux


It might be somewhat simple, but their paid Visual Studio IDE demonstrates no way to get there, and it probably should. The only project types tagged as services are .NET Framework templates to make a Windows service.

I have to apparently read blog posts about how to get there myself with .NET Core. Suffice to say, Microsoft's move to the open source/Linux mindset may have come at the cost of being similarly confusing to get started with.

Note that your blogs happily tell me to add a single NuGet package for Windows or Linux, but doesn't bother to tell me how to assemble a project that will work on both.


> Note that your blogs happily tell me to add a single NuGet package for Windows or Linux, but doesn't bother to tell me how to assemble a project that will work on both.

Well, the rest of the owl is fairly simple in this case.

System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform() can be used to query the OS type, and you specify which builder option (i.e. if islinux UseSystemd ) to use there. I'd type a proper example but on a cell phone.

All of that said, YES you think they would document this better.


I mean, fundamentally it shouldn't even be "documented". They should have a template that just does it. I should select the Service (.NET Core) template, it should give me the start, restart, stop, etc. points to start adding code, and I should be able to select Windows or Linux as build options by default.

Anything that requires I go read a blog post is a massive regression from legacy .NET Framework templates, where I never had to know how a service is built.

Visual Studio has traditionally done most of the heavy lifting on managing scaffolding, but in the past couple releases I've found things are often broken unless I go manually edit some file that I previously never had to edit which can't even be edited from within the IDE.


I'll agree with you there. I'm not a fan of the scaffolding and the overall obtuseness around applicationbuilder, before I understood it the thing felt more unintelligible than a monad burrito to a first year cs student.


Visual Studio 16.8 Preview 2

Tools…Options -> Environment -> Preview Features -> “Show all .NET Core templates in the New Project dialog”

https://devblogs.microsoft.com/dotnet/net-cli-templates-in-v...


Seems like you can just call both UseWindowsService() and UseSystemd(), they will no-op if called on the wrong platform. Personally I think I'd rather split Linux+Windows into thin OS-specific projects, but I haven't tried that. Agreed that a template or better documentation for this kind of multiplatform scenario would be nice.


> Microsoft still lacks a cross-platform desktop UI framework

Avalonia to the rescue: https://github.com/AvaloniaUI/Avalonia


And if Microsoft wanted to bless Avalonia as such, great. In 2020, .NET shouldn't have like three Windows UI frameworks and zero officially recognized cross-platform ones, particularly if they want .NET Core to take off.


>zero officially recognized cross-platform ones

https://devblogs.microsoft.com/dotnet/introducing-net-multi-...

>if they want .NET Core to take off.

Personally I don't need crossplatform (desktop) GUI at all. Backend is enough for me.


Same. No use for desktop GUI apps in SaaS CRUD apps.


I believe x platform ui is planned for net 6, ie nov 2021


Out of everything in the new 5.0 release, I am looking forward most to the non-generic TaskCompletionSource. This is a primitive that has been bothering me for some time WRT tasks that return nothing. I've been resorting to using bool as the generic type argument and discarding the value in these cases.

Also, C# 9.0 is really cool. Will be abusing the new pattern matching stuff once we get a chance to upgrade. Looking like 3.1=>5.0 is going to be a non-event for us based on the current migration guides.


I'm most excited for records and `with`. This is a feature in C# I've been wanting for years and will really help make the use of immutable data throughout a system easier with a ton, and I mean a ton, less boilerplate.


Records are good, although in typical Microsoft style they've elected to call the new constructor syntax "positional" instead of "primary", and then subsequently failed to generalize the feature to normal classes.

With is just building on the anti-pattern where .NET programmers are too lazy to implement constructors.


> "With is just building on the anti-pattern where .NET programmers are too lazy to implement constructors."

What? And aren't records just a lazy way to make classes then?


The new with-expressions are a concession to the existence of initializers, which are themselves literally "stuff that should have been in the constructor" and are incompatible with immutability (hence the new init property hack).

The correct path would have been to require primary constructors for records as the only point of entry for data, declare initializers incompatible with primary constructors, and then just synthesize a method for creating copies - but hey, then you might as well just use Scala.


You seem to not appreciate the prqcticality of immutability in a large system.


Quite the opposite. My language of choice is Scala, which probably explains my frustration at Microsoft's consistent inability to do the right thing.


Speaking about the new records, it bothers me that the keyword in the class declaration is "data" but they call it "record". Why not just name it record? Or "value-data" or something more descriptive? Considering it's one of the biggest languages today, I'm assuming they have ton of people working on it, so I'm clearly missing something here. And why still call it a "class" in the code? Could just have been have keyword instead... So many questions


> it bothers me that the keyword in the class declaration is "data"

The keyword is the declaration is `record`. So you would write your record:

   record Person(string FirstName, string LastName);
Source: I am one of the language designers on C# :)


Huh, reading from https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/ which was the first hit on Google shows the following example:

    public data class Person(string FirstName, string LastName);
It seems https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csh... is saying what you wrote above though.

Seems my previous comment was based on outdated/wrong information, I'm sorry and thanks for clarifying :)

Edit: Seems the post I wrote was published 20th May (probably written before) and that was the same date someone said the same thing as my comment here in the discussion about the "records" feature https://github.com/dotnet/csharplang/issues/39#issuecomment-...


Here is a more recent update on records with the new syntax.

https://devblogs.microsoft.com/dotnet/announcing-net-5-0-rc-...


Ha, I don't know if you worked on this but I had hopes when I saw you'd gone back that maybe we'd finally see records. I'd been seeing your name on record proposals forever.


Is it data? It bothers me as well, but was not the latest blog post with the terminology record?


Shame 'with' will not apply to structs - all the ingredients are already there. Through it might be in the plan for some future release.


As I understand it, making structs implement the record stuff would potentially be...weird. But you're right, it'd be nice.


> I am looking forward most to the non-generic TaskCompletionSource

That has always seemed like a strange omission, but I can't say it's really caused me distress :)

Personally, I'm looking forward to the `half` type, the extra GC diagnostic info, improved app trimming, improved ASN and certificate handling, and of course the improved performance and increased reach of Span. But I think most of all, I'm looking forward to a long term plan and no more .NET Standard/Core mismatch.


The half type is going to be obsolete instantly. There are quite a few other new floating types becoming popular recently: bfloat16, TF32, etc

I wish they made C# support a notion of generic alrgebras.


> I've been resorting to using bool as the generic type argument and discarding the value in these cases.

After seeing other libraries do so, I've fallen into the habit of using a singleton 'Unit' or 'Empty' Type. (This technically also falls in line with the .NET conventions of DbNull.Value and Missing.Value)

Actually, typing that out, I wonder if we all should have been using Missing.Value all along? :)


DBNull is my least favorite part of any version of any .net thing I've ever seen. I hate it with a fiery passion. It forces otherwise sensibly typed variables to be `object`, among a host of other sins.


idk. Null in an object versus null from the database could mean something different so DBNull makes sense.

Also, I don't see how you could say DBNull is responsible for forcing object on us. They could have just as easily made it a struct and i dont see what it would solve.


> Null in an object versus null from the database could mean something different so DBNull makes sense.

Fortunately, it's super easy to tell the difference. `DatabaseQuery()` vs `SomeOtherFunction()`. See?

> Also, I don't see how you could say DBNull is responsible for forcing object on us. They could have just as easily made it a struct and i dont see what it would solve.

Doesn't matter. Even if it was a struct, the only way to store both kinds of value in one variable is to declare it an `object`, even if it was a struct. `null` is a perfectly legal value for a `string` variable, but as soon as the possibility for some other null object (or struct) is raised, the target variable must be `object`. C# doesn't do unions (as a first class language feature anyway).


If you're talking about value types then nullable value types exist, which are still structs:

https://docs.microsoft.com/en-us/dotnet/csharp/language-refe...


None of that helps. A nullable int is `Nullable<int>` or `int?` for short. There is nothing about the language feature that allows you to represent null with a totally different type like `DBNull`, other than declaring your variable `object`. What's the return type of a method that sometimes returns `int` and sometimes `DBNull`? It can only be `object`.

I seem to be having some trouble explaining my point. Maybe this will illustrate better. What should be the declared return type of this method?

    ??? GetValue() {
        if (condition) {
            return 7;
        }
        else {
            return DBNull.Value;
        }
    }


Why do you need to represent `null` with another type? Is this just an issue with DB query results? You can avoid it by making sure the query never returns null or read the values yourself using a type cast test:

int? someNumber = resultset.Records[0]["some_column"] as int?;


Somehow we've gone full circle, and you're arguing my position back to me.

That code sample is exactly how I'd write it. My only problem is that DBNull ever existed in the first place.


There's a difference in certain contexts between 'null' (i.e., a reader that is not initialized) versus DBNull (the value has been set as null by the db or something else). I still think its technically correct.

I get that it was annoying, but most of .NET before 3.5 was anyway. It's just nobody bothered to make the right syntactic sugar.


For callers that care about the distinction, there should (IMHO) have been a GetNullFlavor(). Personally, the number of times I've actually cared is indistinguishable from zero. But the number of times I've had to deal with the infectious stench of DBNull is higher than zero.

Yes, I have a point of view.


My point is that DBNull is only an edge case with DB queries. You can avoid ever dealing with it as I've shown or use an ORM like Dapper or Entity Framework that also handle it for you.

There's really no reason why you have to touch DBNull at all.


I really wish that were true. DBNull is in third-party libraries. And first- and second- too. Check out this code. Dot net really wants me to use DBNull. No database in play at all.

  var dt = new DataTable();
  dt.Columns.Add("name", typeof(string));
  //dt.Columns.Add("count", typeof(int?)); // NotSupportedException: DataSet does not support System.Nullable<>.
  dt.Columns.Add("count", typeof(int));
  var row=dt.NewRow();
  row["name"] = null;
  //row["count"] = null; // ArgumentException: Cannot set Column 'count' to be null. Please use DBNull instead.
  row["count"] = DBNull.Value;
  dt.Rows.Add(row);


Pity that `void` is so special in .net, instead of being a proper unit type (would have avoided the Func/Action duplication as well)


Yeah I definitely miss having an Option<T> or Result<T> type in C# like F# has.

I also don't like that DBNull and Missing are reference types, it would be better to use a value type for this to avoid having to do null checks similar to Nullable<T> but I guess in this case it doesn't matter since they are used for different purposes.


I'm excited about new native interop api (function pointers, UnmanagedCallersOnlyAttribute, etc.). It removes "managed code tax" for calling into dynamically loaded OpenGL/Vulkan methods from c#.

I'm playing around with GLFW via PInvoke, which meant marshalling openGL function pointers into managed delegates. In net5.0 preview, I can simply cast IntPtr into a function pointer, and boy, a call to your average openGL method is literally an order of magnitude faster.

Similar optimizations might have been technically possible before, but it required some icky bytecode tinkering.


> It removes "managed code tax" for calling into dynamically loaded OpenGL/Vulkan methods

Interesting, never heard of that. Do you have a source?

I haven’t noticed much overhead when I measured, take a look: https://github.com/Const-me/ComLightInterop#how-it-works That library compiles and runs with .NET Core 2.1.

Update: also there https://docs.microsoft.com/en-us/cpp/dotnet/calling-native-f... they wrote “PInvoke has an overhead of between 10 and 30 x86 instructions per call”

It roughly corresponds to my observation, and I find it fast enough for all practical applications, including GLES rendering on ARM Linux: https://github.com/Const-me/Vrmac/


This sounds very interesting. I didn't realize there was that much of a difference using the new APIs.

I have been playing around with interop against LibJpegTurbo Encode() and I am now curious if I've been leaving a ton of performance on the table.


Sounds really interesting. Do you have samples, benchmarks or other resources you can share?


Can someone please explain what .NET framework is? Everytime I come across it, it seems like a mysterious microsoft thing and Wikipedia's explanation is even more confusing:

> .NET Framework (pronounced as "dot net") is a software framework developed by Microsoft that runs primarily on Microsoft Windows. It includes a large class library called Framework Class Library (FCL) and provides language interoperability (each language can use code written in other languages) across several programming languages.

What is .NET framework really?

Elsewhere, it is described as "A framework to build applications in Windows", but I thought that's what the Windows API helps with.

Any help with clarification would be great, thank you.


.NET was built in the time of early Java, and so has many similar characteristics: virtual machine with a garbage collector, executes compiled processor- and OS-independent binaries, supports multiple languages, and a large class library. A lot of these early bets were good. .NET has been used in almost all the relevant computing devices today, to greater or lesser degrees of success (not all from Microsoft).

More recently, .NET has been focused on cloud native space and high-performance web applications. It has been open source and cross platform for about 5 years now.

Here's an example of work we've done for containers: https://devblogs.microsoft.com/dotnet/using-net-and-docker-t...

Here are two good blog posts to demonstrate what we've been up to performance-wise:

https://devblogs.microsoft.com/dotnet/performance-improvemen...

https://devblogs.microsoft.com/dotnet/arm64-performance-in-n...


> What is .NET framework really?

At its core: It’s what Microsoft made to compete with Java back in 2002.

It’s a development platform, with associated tooling, compilers and a runtime. It has a common standard-library independent of language used by the developer (which aids cross-language interop), but realistically speaking most people just use C#.

You can use it to create network services, console applications, web assembly programs or desktop GUI applications. It’s quite versatile.

And .NET 5 will seemingly be the first version to officially supersede the previously Windows-only “.Net Framework” with a modern, open-source, cross-platform version instead.

As a Linux desktop-user, I’m loving it.


Are you building and/or using any .NET desktop GUI applications _on_ linux? I'd love to poke around some open-source projects to see how these are being made today.


I've built this: https://GitHub.com/qmlnet/qmlnet

I used it in medical devices within some of the larger medical device companies.



> And .NET 5 will seemingly be the first version to officially supersede the previously Windows-only “.Net Framework” with a modern, open-source, cross-platform version instead.

You don't count .Net core?


.net core ran in parallel with .net framework

.Net 5 is where they drop framework and core actually supersedes it


If it is any consolation, Microsoft's description of .NET at its first launch was even more nebulous than that. I avoided it out of sheer confusion at how it was going to wax my car, do my taxes, and save my soul.


Haha. Inspite of the hyperbole, MS did manage to steer .NET very well.

I only wish there were more libraries in the Data Analytics area, something akin to Pandas library in Python.


I suppose that it's very similar in spirit as Java, with the difference that Microsoft presented in a more encompassing way (assuming that the definition of "software framework" was given by MS).

Often in fact Java is described as a language, while, at a minimum, a Java distribution includes the JVM and the standard library.

Describing as a software framework is therefore (in this sense) more exact, as the .NET framework includes the CLR and its standard library (and possibly, other components).

The difference with the Windows API is that they are lower level. The simplest possible component one may think of is probably LINQ - querying functionalities are intuitively higher level than system APIs.


It’s huge, has 2 decades of legacy, and has many parts. Here’s the main ones.

1. Virtual machine and JIT compiler, usually called CLR = Common Language Runtime, it runs byte code called CIL = Common Intermediate Language. They have renamed it a few times; older docs/tools may call the byte code MSIL = Microsoft Intermediate Language, or just IL. In modern .NET this thing is platform-agnostic.

2. Standard libraries for that runtime. The modern implementation is called CoreFX. It includes large count of batteries: collections, LINQ, threading and synchronization, async-await runtime, reflection, and much more. Fortunately, CIL is very compact representation of code, takes a small fraction of an AMD64 equivalent.

The lower-level pieces are platform-agnostic, but there’re many windows-only pieces implementing GUI and integration with other OS-specific services like WMI, registry, ADSI and more. For WinForms and similar they just use [DllImport] to consume Win32 and GDI+. For WPF this includes large amount of compiled C++ DLLs that consumes DirectX 9 to render GUI and implement resource-intensive algorithms. For UWP this includes COM interfaces to call native Windows APIs (albeit these interfaces might be a part of Windows SDK, I’m not sure).

3. Programming languages and compilers for them, the main ones supported by MS are C#, VB.NET, and to lesser extent F#. Modern version has a single compiler for C# and VB called “Roslyn”, F# is a separate program. There’re third-party ones, see IronPython. Also some .NET based products include their custom compilers or code generators who produce CIL code from something else in runtime, I did it a few times, not too hard.

There’re smaller pieces like framework SDK (a set of command-line tools to create, compile and run projects), msbuild (a build system typically used on Windows or for larger projects), and many other random programs/libraries of varying utility.

Update: Forgot an important component, NuGet package manager. It’s an equivalent of Python’s pip, or JavaScript’s npm, an online repository of code packages. The majority of packages there only contain CIL code, i.e. they’re very small and platform-agnostic. The most popular package there is an alternative Json parser, was downloaded 650M times. Microsoft uses nuget to deliver optional pieces of the standard library, developers like me are publishing their weird libraries too https://www.nuget.org/profiles/ConstMe


You missed C++/CLI.


Yes. Also .NET native, remoting, WCF, asp.net, and lots of other things. Two reasons.

1. The ecosystem is huge. People are writing thick books on these subjects.

2. Most of the above (except asp.net) is windows-only stuff. Even on Windows, the stuff most useful if you’re maintaining something from 10-20 years old, less so for new projects, at least in my experience.


Well, C++/CLI support was the biggest feature for the .NET Core 3.0 release, so it does matter.

Although I do concede that most likely Microsoft would happily get rid of it, and have everyone make use of C++ code in .NET via UWP components instead, preferably using C++/WinRT.


This is a pretty good explanation video about the .NET ecosystem in general: https://www.youtube.com/watch?v=bEfBfBQq7EE


To simplify things you can say that .NET consists of three things:

1) A garbage collecting virtual machine (like the JVM) that executes Intermediary Language (IL) by just-in-time compiling it to native code.

2) A set of programming languages (C# being the most popular) that compiles to IL.

3) A broad set of libraries that are part of .NET or available from the NuGet package manager. This includes basic features like collections, JSON serialization and cryptographic primitives but also huge frameworks for web development using databases etc.

In recent years Microsoft has open sourced big parts of .NET and basically rebuilt it from the ground up to make it cross platform. In the process a lot has been improved in terms of usability and efficiency making .NET a serious contender when it comes to building something like large scale cloud applications.

The next major release of .NET is expected in November where the "old" Windows only version and the new improved cross platform version (.NET Core) will converge into .NET 5.


A really handwavy description would be that it's kinda like a "runtime".

It's very roughly analogous to the Java Runtime Environment (JRE). .NET binaries are very roughly like JAR files.

(I realize the analogy is rough, but I think it would connect with folks who've never worked with a Microsoft stack)


You would definitely be excused for feeling puzzled. I got thrown into a full time cross-platform .NET development role with zero experience in .NET, and figuring out how it all fit together (especially a couple of years ago) was a nightmare.

I wrote down some of my discoveries here: https://two-wrongs.com/dotnet-on-non-windows-platforms-brief...


Has anyone here used (or are familiar with relevant cases of using) .NET for developing startup products, including MVPs? With some exceptions, I'm seeing .NET as predominantly an enterprise-focused technology. Strategizing about development of my MVP (B2B enterprise platform), as a CTO, I'm torn between a) Python and its great ecosystem (I plan to use FastAPI instead of more traditional Flask and Django), b) C# and .NET ecosystem and - to a lesser degree, for the reasons explained below - c) Julia and its emerging ecosystem.

As much as I'm excited about Julia, I think that both the language and the ecosystem have not yet reached enough maturity and critical mass of developers as well as comprehensive and stable general-purpose libraries and tools to be a safe choice for a startup, which is already a highly risky venture. I have to reduce risks, not add ones.

Between Python and .NET ecosystems, I'm more familiar with the former and, under equal conditions, would choose it over .NET. Additional argument in favor of this decision is that most of advanced ML/AI development is focused on Python high-level interfaces (and ML/AI is certainly a significant part of my future platform's value proposition). However, based on my research and recent .NET experience, I recognize its advantages versus the Python stack in some areas, including native type system support (though pydantic might be good enough for the Python stack; plus, it is used by FastAPI), rich set of native APIs, much better performance, much better support for domain-driven design (DDD), WebAssembly support, and, finally, much better support for developing multi-tenant applications. The last item is especially important in my case, since multi-tenancy and other relevant features (e.g., auditability) are strict requirements and Python ecosystem pales in comparison with .NET in this regard (the only decent project that I ran across is django-tenants, but a) it would force me to use Django and b) it only supports PostgreSQL schema-based multi-tenancy approach).

Would love to hear your opinions and thoughts on the above. Thank you in advance!


I'm using .NET Core/F# for the backend of my bootstrapped "startup". I mostly have an iOS dev background so take my experiences with a grain of salt.

So far everything has gone pretty smooth. ASP.NET Core is running under the hood which seems to be pretty mature. F# and the libraries that I work with all provide a functional development experience. I interface with a Postgres database, so there's libraries for that as well.

You mentioned Domain-Driven Design. I would recommend reading Scott Wlaschins book Domain Modeling Made Functional [1].

If you are interested in playing around with F#, a quick way to start would be to try SAFE stack [2].

From what I have read during the last couple of months, MS seems to be interested in pushing F# as one of their go-to languages for machine learning. At least they have an F# example online [3], which can not be said for most other areas where F# would also be a good fit in my opinion.

[1] https://fsharpforfunandprofit.com/books/ [2] https://safe-stack.github.io [3] https://dotnet.microsoft.com/apps/machinelearning-ai/ml-dotn...


Much appreciate your feedback and advice. I was considering using F# instead C# for my potential .NET-based solution. But not because of Microsoft's ML push for F# (which seems to be just a move to achieve feature parity with C# within ML.NET framework, which, by the way, is not as comprehensive as relevant Python ecosystem), but rather because of F#'s meta-programming features. However, the advantages of F# still do not overweight its IMO two main disadvantages: a much more limited (vs. C#) pool of available developers and limited support by tools beyond Microsoft ecosystem (e.g., by JetBrains products).


> a much more limited (vs. C#) pool of available developers

I don't plan to hire anyone in the foreseeable future but what I can say is that there's 2 people happily working on the F# codebase at the moment, that do not have any prior experience in the language (professional Swift/ObjC background and played around with other languages). Getting into it is quite easy if you're interested in FP. I wouldn't worry too much about that. Just get some people who are experienced in .NET and some people who are good in FP.

> limited support by tools beyond Microsoft ecosystem (e.g., by JetBrains products)

I use JetBrains Rider on a Mac, without major problems so far


Fair enough. Thank you, will keep this in mind.


Google Jetbrains Rider.

Do not worry about the pool. The limiting factor in finding good people is the good part not the programming language.


Thank you for sharing your thoughts. I'm aware of JetBrains Rider. In fact, I have installed it on my desktop and used it to explore the above-mentioned .NET boilerplate templates (C#-based). Perhaps, I missed that Rider fully supports F#. Will check it out.

Re: finding good people - I certainly agree with importance of focusing on the good part. However, still ... having a significantly larger pool of developers statistically increases chances to find good ones (which is important, especially considering competition with big tech firms in hiring engineering talent).


Does it?

I mean, if I see a good developer who is interested in learning F#, that means I have found a good developer who is interested in learning something off the beaten path.

For certain organizations that is exactly what they need.


I think that you're missing my point about the statistical nature of engineering talent hiring. My argument is that you will have higher chances to "see a good developer" in the first place, if relevant pool of potential candidates is larger (of course, under other equal conditions).


There's another point of view: that by targeting people who either know, or are interested in learning F#, or any other less popular language (like Rust, Erlang, Julia, etc.), you massively increase the quality of your applicant pool.

Developers that just want to pay the bills learn the popular languages: Python, javascript, Java, C#, Swift, etc. Developers who plays with (or maybe find little projects to do with) the like of F# are statistically more likely to care about their craft, even if they don't necessarily have the possibility to use these at their current jobs.

If someone contact you specifically because they want to use an FP language, but they can't at their current job, it's a very good sign. Of course if you limit yourself to something like: 5 years of experience writing F# in insert field of interest here, it's going to be very tough to hire anyone...


Generally, I agree with you, except for the argument that developers who play with (or do projects using) less popular languages "are statistically more likely to care about their craft" (do you have any data supporting this claim?). Being curious, while certainly a valuable trait, is not equivalent to "being caring" about some craft - it is a nice addition to the package. However, it is a bit more nuanced than that. For example, success or failure in using this strategy depends on startup's stage, funding, roadmap, team size, engineering culture as well as current or potential use of microservices architecture, which gives us much greater flexibility in a relevant technology stack selection.


But if you hire "programmers" and train them in F# on the job instead of looking specifically for "F# programmers" you sidestep that problem.

My organisations job ad is looking for people with "several years of programming experience by the way we do things in C# and F# but do not expect you to have".

Then we weed out the huge majority by issuing a tiny take-home code test (think a few fizzbuzz-style questions) that applicants can complete in whatever language or environment they want.

So far, we've received positive feedback on the approach, but also very few truly talented applicants. I think the latter is because we're extremely picky, but I don't know.

What I do know is that we wouldn't get better or more qualified applicants by limiting our search to a few languages. Some of the best so far have come with a language we would never have thought to list.


Thank you for sharing your feedback. Your approach certainly makes sense and I'm also not a fan of listing specific programming languages (as well as stacks, frameworks, platforms or products) as strict requirements. However, in my book, it makes sense only for mature companies and later-stage startups. Early-stage (especially, bootstrapped, small and non-VC-backed) startups simply cannot afford to spend time for training on the job.


I think with the right, bright people, they'll train themselves in no time. But sure, that shifts the problem from getting "people who know F#" to "people who are very intelligent and experienced", which might be equally hard if not more so.

I believe it's worth it, but have no data to back it up.


Fair enough.


Very good point regards training on the job. Indeed a factor to consider in discussion about early stage recruiting!!!


Thank you!


Another aspect of that: do not do functional programming then. There are statistics for .NET which surely also apply to most languages: 10 million C# devs, 1 million VB.NET devs and 100k F# devs. By requiring functional programming the candidate pool shrunk by a factor of 100.

There is certainly a higher factor of high talent in FP capable programmers but at the same time the risk for bad hires due to lacking people skills or overly dogmatic work style increases.


Good points. Thank you for bringing them up.


I've been building startups for 15 years using .NET

It's incredibly fast and productive and has allowed me to create more as a single-person than entire teams using other languages. That still remains true today, even more so as it removes many of the limitations of the Windows-only desktop framework.

Even if you can't use C#/.NET for all the functionality you need, there are many ways to interface with other stacks from function calls, inter-process communication, RPC frameworks, etc. It's well-supported and very common now with the rise of microservices anyway. For AI/ML specifically, I suggest looking at the Machine Learning docs which list plenty of projects like ML.NET and integrations for Tensorflow and Spark.

https://dotnet.microsoft.com/apps/machinelearning-ai/


> It's incredibly fast and productive and has allowed me to create more as a single-person than entire teams using other languages.

Another startup founder and CTO here. Can confirm this. Once you get to know the framework, it's really hard to describe how productive you can become. Static type checking, fast compile times, LINQ!, ... It's a 10x ecosystem in the hands of competent developers.

So, our back-end and business logic is in .netcore/C#. Our front-end is a desktop app written in Java 11/JavaFX. The two communicate with a thin IPC layer (stdio pipes). With "new" java (11 and onwards) I'm almost as productive as with C#. If C#/.net is 10x, I'd rate Java as 8x.


Thank you very much for sharing your thoughts and experiences. Please see my reply to the parent comment (by @manigandham) about one of .NET-side reasons for my contemplation. I'm curious about your opinion on this aspect.


In that comment you're comparing a statically-typed language (C#) with a dynamically-typed one (Python) and your main concern is that C# libraries feel "overengineered". This totally makes no sense to me because the whole development methodology will be different between the two. I.e., it makes no sense to me because your concern is the most shallow one.

And yes, using a statically typed language with strict typechecking (i.e., no implicit integral conversions like in C and C++) leads to programs that feel "engineered" (I wouldn't say overengineered) but which are easy to confidently refactor and build upon.

IOW, flexible/productinve language + static typing + good IDE (VS) = easy to develop "obviously correct" code that works when it compiles and which obviates the need for a huge battery of tests. IME.


Thank you for sharing your thoughts. I certainly agree with you on benefits of using statically-typed languages (and this is one of the reasons for my potential selection of C# versus Python - though, mypy and pydantic packages seem to alleviate some/many/most(?) of Python's type-checking issues). However, that was not my point or concern. My reference to most C# code that I have seen felt as "overengineered" has nothing to do with language type systems and type checking (if anything, it leads to verbosity, but not overengineering). I thought that I clearly mentioned what specific aspects of the code produced that feeling for me: a "proper" implementation of design patterns, DDD and enterprise-focused features.


I appreciate your feedback. I definitely have a very positive feeling about .NET Core (C# and, to lesser degree, F#) platform (though, I think that .NET ecosystem is not as comprehensive / diverse as the Python one). What forces me to contemplate about .NET versus Python is that most of the C# source code I have looked at (especially ABP frameworks) have a feeling of being over-engineered / "heavy" (versus Python's being elegant / "light"). I understand that most of that comes from a "proper" implementation of design patterns, DDD and enterprise-focused features (which, actually, I need, by the way - hence my interest in ABP frameworks). But, still this feeling troubles me a bit. Perhaps, I just need to read and practice more in C# and .NET ... :-)


You can write complete C# apps in a single file if you want. It's not really that verbose (nowhere near Java). The structure and the huge standard library helps greatly compared to the messy nature of other languages like JS and Go that ends up with code and modules everywhere. You'll quickly learn and maneuver around the bigger patterns, which (like you say) are actually important in working with larger applications.

But nothing I say will be as useful as just working with it. Try spending a few hours working with some of the bigger frameworks and I'm sure you'll get it pretty quick. If you need help then there are plenty of people to ask as well, from HN to twitter to the .net repos.


Thank you for sharing your thoughts on this. I have already spent more than a few hours with the two large enterprise SaaS boilerplate frameworks that I mentioned above and, while I understand most concepts, it still feels quite overwhelming.

Now the question becomes whether it is worth spending time and effort learning more in terms of design patterns, DDD (maybe even CQRS and Event Sourcing) and specifics of these large third-party frameworks as well as practicing working with all that with a benefit of developing really solid enterprise-ready SaaS platform from the start VERSUS moving much faster by developing a more lightweight MVP in Python/FastAPI stack (with PostgreSQL / GraphQL / Vue in both cases) - still with basic/core enterprise features like cloud-native scalability (using Docker swarm mode) and multi-tenancy (using PostgreSQL row-level security) - with a disadvantage of having somewhat less solid architecture and/or some technical debt initially.


Well first of all, do you really need all that? How "enterprise" is the solution you're building? DDD is very involved and more academic than realistic. And you definitely don't need CQRS/Event sourcing, that's firmly in exotic territory for most projects.

There's a lot to enterprise stuff that also has nothing to do with the tech [1] so I would recommend starting with the default asp.net templates and build from there. Move fast and then add in the enterprise specific patterns when you need it.

1. http://www.enterpriseready.io/


Yes, I do need all that (except for CQRS and Event Sourcing, which I've briefly looked at and didn't like them, plus, they only make sense for certain types of systems based on microservices architecture). Yes, I'm familiar with relevant requirements and the EnterpriseReady project, in particular. Having said that, I certainly don't need all enterprise features for the MVP. How "enterprise" my market-ready solution should be? As comprehensively as most and then some. The solution's target market includes (mostly medium and large) industrial enterprises, government agencies and universities.


I've worked at a startup that did this.

I don't know if this was the program we used, but you can get a LOT of free stuff from Microsoft as a startup. https://azure.microsoft.com/en-us/overview/startups/

>Between Python and .NET ecosystems, I'm more familiar with the former and, under equal conditions, would choose it over .NET.

I think one thing you need to do when creating a startup is, go with what you know (as you said). You want to decrease the risk that you're product is going to be blocked by encountering an edge case in a framework/language you don't know and you get stuck there for a long time. I am way more familiar with .NET than Python, but I use Python in my spare time and on side projects to build up those muscles.

If you're doing a startup and you want to go .NET, I don't think there's anything holding you back anymore. It's open source now, runs on Linux, and you don't have to pay a dime to develop with it. Microsoft will get you in that, it's WAY easier to pay a little bit to get Visual Studio Enterprise and to then hook that into Azure and all of a sudden you're paying them a ton of money. Yes, that's their master plan. But, no one is making you do that.

Where to stay away from .NET core: Lambdas. The startup time for Lambdas just isn't where it is for other languages, when I last looked at this. If someone has newer data to prove me wrong I'll freaking LOVE YOU FOREVER!

Anyway, depending on what and how you're building your startup, .NET maybe a great pick for you depending on your background. I wouldn't force myself to pick up a new ecosystem and do a startup if I was focused on delivering a product I wanted to deliver and not learning something new and cool.


Visual Studio Code is great and Jetbrains Rider is much cheaper and very capable. You can skip VS Enterprise for most projects, and the Professional version also costs a lot less if you just need advanced debugging.

Also Azure isn't really necessary at all considering the ubiquity of Docker and Kubernetes. I've been running .NET programs basically everywhere else other than Azure for a long time.


1000% Agree with everything said here.

Microsoft makes is stupid easy to use Azure, but that doesn't preclude how easy it is to use other hosting. It's like, you can have an iPhone and a windows laptop, but it doesn't integrate AS well as iPhone and a Mac.


Great feedback, much appreciated! I'm familiar with Microsoft for Startups program and I'm still considering it, though currently it's not a priority. I agree with most of your thoughts above. Don't have experience with .NET-based Lambdas, though, so I don't have an opinion on that yet. As for what I'm building, well ... I'm building a comprehensive (read: large) and complex B2B enterprise SaaS platform focused on a particular multi-disciplinary scientific domain. I'm a solo founder and have technical (and research) background, including software development and IT architecture experience.


I worked for two consultancies that basically created apps for multiple startups and we used .NET Core in almost all projects. I don't really have comparison because besides simple, personal Django projects I never had much experience with Python but I find .NET Core actually enjoyable(I come from Android Java/Kotlin world). I don't like the community which is, mostly still stuck in the enterprise(though that's changing alowly) and often feels like an MS cult, but otherwise, there's nothing bad I could really say about .NET. Especially when paired with Azure ecosystem, it's really easy do develop and deploy, it's really fast, easy to work with thanks to Entity Framework and stuff like LINQ, there's a lot of choice in libraries. Some are still stuck in .NET Framework(Windows) world, but most of Nugets already implement at least netstandard2.0 which allows you to use them with Core. In overall, especially now with Blazor becoming a thing, I'd recommend at least trying it out.


I appreciate your prompt feedback with interesting details. Re: Blazor - while it's definitely a promising technology, I'm not sure how suitable it is for building SPAs. One potential issue that I can see is quite limited (and IMO very expensive, e.g.: https://www.syncfusion.com/sales/products/blazor) UI components ecosystem, when compared to the React/Vue/Angular one (I plan on using Vue).


You might qualify for the Syncfusion Community License: https://www.syncfusion.com/products/communitylicense

Radzen also has a component library available: https://blazor.radzen.com/

https://abp.io/ recently added Blazor to their framework that you might want to check out.


Thank you for your advice. The Syncfusion Community License is certainly interesting and I will keep it in mind (as well as Radzen). Though, frankly, I don't like these "lure into an ecosystem/platform/product with free goodies and then lock in to a very expensive deal" approaches. I prefer a decent progressive pricing tiers model. Re: ABP and Blazor - yes, I read about that, but I think that it is still an experimental feature: https://github.com/abpframework/abp/issues/394.


I didnt specify but we actually mostly use server side Blazor for now. The only issue with it so far is lack of proper hot reload which is annoying but manageable. Otherwise, it's really great. It's kinda an equivalent of Phoenix' LiveView. You only really send diffs over the wire, everything happens on the server, code sharing is very easy and makes developing very, very fast. Sure, SignalR might not be that scalable but IMO unless you're a giant with tens of thousands of active users at any given moment, I wouldn't care.


Interesting and good to know. Thank you for your additional clarifications. I would love to get my hands dirty with Blazor and many other technologies. The problem with being a very early-stage startup, despite being very tempting to jump the cutting edge bandwagon and (try to) use as many cool technologies as you can get your hands on, is to keep in mind the importance of risk management. More often than not, it makes sense to select a "boring" technology stack (http://boringtechnology.club), at least, for all or certain foundational layers or components of the larger system.


I don't quite get the hype around Blazor. Great idea but the implementation is a non-starter considering it has to send a whole runtime over the wire.


Blazor is the first frontend component model framework built for the web that isn't older server-side templating and also not Javascript. Using a strong typed language like C# makes it very fast and productive, especially when reusing the same code and libraries with your server backend (something that was touted with node/JS but has been weighed down by the chaos of the JS ecosystem).

Blazor can also run in 2 modes:

1) server-side where the UI is controlled by a websocket (via SignalR) connection to the backend which processes all the logic. Developing complex interfaces becomes much easier because everything runs on the server and the distance between a database query and UI update is very short. Save the verbose JS->API->Backend layers of code.

2) client-side which uses cutting edge WebAssembly to run your app. The WASM version is getting smaller and faster with every release and isn't much bigger than your standard big SPA which also has megabytes of javascript these days. It has a great JSON library and can also support GRPC-Web now for easy RPC.


Typically modules come with their own contracts. Even in the backend by itself, we see same class definition as a model, as an entity and as a business object. OOP also had goals regarding reusability (see criticism section - https://en.wikipedia.org/wiki/Object-oriented_programming). Reusing the same code is hard.


True, but it's much harder in some languages than others, and much much harder when crossing language boundaries.

Copying a C# class to use as a DTO from a database entity is way faster than trying to worry about serializing to a JSON structure while maintaining all the fidelity (like dates, big ints, binary data, etc).

Another example is reusing business logic like validation for data input. Blazor lets you use a single layer of logic instead of using JS-based simple validation on the form and more detailed checks on the server.


We use it in server-side mode (no WASM assembly to deliver). SSB is incredible for apps where you are expecting a well-bounded number of concurrent users.

We use it for internal business dashboards and devops management tools. The ability to inject & use existing .NET services is pretty incredible in terms of productivity. We now maintain a monorepository because of this reuse potential.

https://docs.microsoft.com/en-us/aspnet/core/blazor/hosting-...


It's amazing. I've been using server side blazor and it's been quick to develop, performant for users, and more interactive than SSR.

Down side is scaling, but I mostly write B2B apps. And by the time you run into scaling issues in B2B SaaS someone's rich.


> Has anyone here used (or are familiar with relevant cases of using) .NET for developing startup products, including MVPs?

Yes, I have. I've been programming with C# since it was first released, so we're very well acquainted, and I can build MVPs quickly. As always though, it depends what you are used to.

> I'm seeing .NET as predominantly an enterprise-focused technology

I didn't see it as any more enterprise-focused than Java, andid say less so since dotnet core brought multi-platform support.


Thank you for your feedback. When I said "predominantly an enterprise-focused technology", I meant overall popularity for building in-house enterprise products versus developing startup products. Anyway, should I decide to use .NET, I would most likely use a high-quality boilerplate solution as a foundation. Specifically, I'm a big fan of (and have already played with) ASP.NET Boilerplate and its next-gen version called ABP Framework. They also have relevant attractive commercial versions.


I should have been clearer, but I meant for building MVPs for side-projects and startups (although I have actually built many an MVP with C# in the Enterprise world too).


I see. Thank you for the clarification.


I'm using .NET Core/C# as my backend for a WebXR project for remote learning of foreign languages. After a brief learning curve with ASP.NET Core (I used to do a lot of WebForms work before pivoting hard into VR) I'm enjoying it a lot.


Cool. Thank you for your feedback and good luck with your project.


Use what you know and run fast. Any day you've spent debating this is a day you aren't closer to shipping.


Thank you for your advice. I understand where you're coming from, however, I respectfully disagree (plus, in my case, your advice is not much applicable, since my knowledge and experience with Python and .NET ecosystems are not that much different - I still will need to master quite a lot of topics and aspects). If I would be debating which UI styling to use, which relational database to use or even which front-end framework to use, I would agree that it does not matter that much and should be based on existing knowledge and skill set. However, I strongly believe that spending enough time to select the best/optimal technology stack for the target product is worthwhile and will provide a high return on investment. You don't want to skimp on architectural decisions, since fixing the wrong ones will cost much time, money, effort and, sometimes, will even be outright impossible. Hence my deliberation.


My startup's target is actually to close the AI gap. We are re-exposing the entire TensorFlow Python API in C#: https://losttech.software/gradient.html


I assume you are aware of Direct.ML and its Tensorflow integration?

https://cloudblogs.microsoft.com/opensource/2020/09/08/open-...


Yep, and it is currently many times slower than CUDA version on Nvidia. Haven't had an opportunity to compare tensorflow-rocm with it on AMD yet.


Sure, all the best for your endeavours. We need better managed language support for GPGPU.


Thank you for chiming in. Interestingly enough, I ran across your startup not long ago, when exploring ML/AI landscape of the .NET ecosystem. Good luck with your venture. By the way, do you have plans to support other popular frameworks beyond TensorFlow? Just curious.


There's no plan to support any non-NN frameworks.

We might decide to add PyTorch support, if its adoption will continue to accelerate. But that won't happen for at least a year.


Understood. I certainly didn't mean non-NN frameworks, but rather meant other popular NN ones (PyTorch, MXNet, etc.).


> I plan to use FastAPI instead of more traditional Flask and Django

Why?


Because FastAPI is much faster* than both Flask and Django (see https://www.techempower.com/benchmarks/#section=data-r19&hw=...), supports Python type hints, is a great fit for my target architecture (SPA), supports both RESTful and GraphQL API styles, offers built-in validation and much more (https://fastapi.tiangolo.com/features).

*) Having said that, from the performance perspective, .NET Core and Julia (from my options) are certainly much more tempting.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: