Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update C# templates to top level statements #5071

Closed
RussKie opened this issue Jun 10, 2021 · 12 comments
Closed

Update C# templates to top level statements #5071

RussKie opened this issue Jun 10, 2021 · 12 comments
Labels
area-Templates enhancement Product code improvement that does NOT require public API changes/additions won't fix: compat

Comments

@RussKie
Copy link
Member

RussKie commented Jun 10, 2021

Top level statements have been released in .NET 5 and C# 9. There are a number of active internal discussion about updating other templates (e.g. ASP.NET Core) to use the top level statements approach.

As discussed in dotnet/designs#223 (comment) C# Windows Forms apps can be written as top level programs today as well, though [STAThread] make it a little awkward. So we can consider updating our application template

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Company.WinFormsApplication1
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}

...and rewrite it as follows:

using System.Threading;
using System.Windows.Forms;
using Company.WinFormsApplication1;

// It is unfortunate but we have to set it to Unknown first.
Thread.CurrentThread.SetApartmentState(ApartmentState.Unknown);
Thread.CurrentThread.SetApartmentState(ApartmentState.STA);

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(defaultValue: false);
Application.SetHighDpiMode(HighDpiMode.PerMonitorV2);

Application.Run(new Form1());

When dotnet/designs#223 will be implemented the template can be further simplified, and would look something like this:

using System.Threading;
using System.Windows.Forms;
using Company.WinFormsApplication1;

// It is unfortunate but we have to set it to Unknown first.
Thread.CurrentThread.SetApartmentState(ApartmentState.Unknown);
Thread.CurrentThread.SetApartmentState(ApartmentState.STA);

ApplicationConfiguration.Initialize();

Application.Run(new Form1());

And, generally speaking, there's nothing that prevents moving Thread.CurrentThread.SetApartmentState(...) calls into the source generated ApplicationConfiguration.Initialize() method:

using System.Threading;
using System.Windows.Forms;
using Company.WinFormsApplication1;

ApplicationConfiguration.Initialize();

Application.Run(new Form1());
@RussKie RussKie added enhancement Product code improvement that does NOT require public API changes/additions area-Templates labels Jun 10, 2021
@RussKie
Copy link
Member Author

RussKie commented Jun 10, 2021

image

@AraHaan
Copy link
Member

AraHaan commented Jun 12, 2021

I would rather the Application.Run() to also be moved to the Initialize method that is source generated and take in the form instance that should be new'd up in that call so it could be simplified to just:

// make these global usings in "GlobalUsings.cs".
using System.Threading;
using System.Windows.Forms;
using Company.WinFormsApplication1;

ApplicationConfiguration.Initialize(() => new Form1());

So then in the end the actual Program.cs file could then be chopped down to just a single line of actual code with the Initialize method running that lambda inside when it calls Run for you.

@RussKie RussKie added the Priority:1 Work that is critical for the release, but we could probably ship without label Aug 16, 2021
@RussKie RussKie added this to the 6.0 milestone Aug 16, 2021
@RussKie
Copy link
Member Author

RussKie commented Aug 25, 2021

We won't be changing our templates to use the top level statements (#5071). A typical Windows Forms app consist of multiple types split across multiple files (e.g. Form1.cs and Form1.Designer.cs) that won't work with top level statements.

@RussKie RussKie closed this as completed Aug 25, 2021
@ghost ghost removed this from the 6.0 milestone Aug 25, 2021
@RussKie RussKie added won't fix: compat and removed Priority:1 Work that is critical for the release, but we could probably ship without labels Aug 25, 2021
RussKie added a commit to RussKie/winforms that referenced this issue Aug 25, 2021
RussKie added a commit to RussKie/winforms that referenced this issue Aug 26, 2021
RussKie added a commit that referenced this issue Aug 26, 2021
@Amy-Li03
Copy link
Contributor

@RussKie Verified this issue on .NET 6.0 RC1 latest build: 6.0.10-rc.1.21417.19 + binaries build from main branch under dotnet/winforms repo, after replace following codes in Program.cs file:

Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

with
ApplicationConfiguration.Initialize();

this code is not recognized as following screenshot, want to confirm with you do we need to do some other actions at here?
image

@RussKie
Copy link
Member Author

RussKie commented Aug 26, 2021

<LangVersion>preview</LangVersion> in csproj until .NET 6.0 goes GA.

@Amy-Li03
Copy link
Contributor

You mean preview will show in csproj until .NET 6.0 goes GA, we can verify this issue at then?

@RussKie
Copy link
Member Author

RussKie commented Aug 26, 2021

We use Source Generators API v2, which are behind the "preview" lang version. @chsienki @sharwell the langversion=preview won't be require when .NET 6.0 GAs, right?

@chsienki
Copy link

@RussKie We just (today) merged the change that removes the requirement. .NET 6.0 GA will enable V2 generators by default.

@RussKie
Copy link
Member Author

RussKie commented Aug 27, 2021

Awesome! 🎉

@Amy-Li03
Copy link
Contributor

Amy-Li03 commented Aug 30, 2021

Verified this issue with .NET 6.0 RC2 latest build: 6.0.10-rc.2.21429.3, when using ApplicationConfiguration.Initialize() method on Program.cs or use top level statements, winforms .NET core project can build and run successfully.

image
image

@AraHaan
Copy link
Member

AraHaan commented Aug 30, 2021

Does this mean it also adds the [main: STAThread] to the top level program in that case?

@RussKie
Copy link
Member Author

RussKie commented Aug 31, 2021

AFAIK there is no such thing as [main: STAThread], though it is being discussed.
In the case of top level statements ApplicationConfiguration.Initialize() emits this:

// Set STAThread
Thread.CurrentThread.SetApartmentState(ApartmentState.Unknown);
Thread.CurrentThread.SetApartmentState(ApartmentState.STA);

@ghost ghost locked as resolved and limited conversation to collaborators Jan 28, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-Templates enhancement Product code improvement that does NOT require public API changes/additions won't fix: compat
Projects
None yet
Development

No branches or pull requests

4 participants