-
Notifications
You must be signed in to change notification settings - Fork 162
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
Add Simple C# Programs #213
Conversation
Co-authored-by: Fred Silberberg <fred@silberberg.xyz>
Do the commands Also, is there a chance to evolve CSX to meet these introductory/scripting demands, while keeping C# structured? Because when I see a |
It is also worth pointing out that Furthermore it makes sense to have the compiler enforce the exact same semantics for these directives as for c# scripting. If new features like framework references are needed here, then scripting could benefit from them too. There are already requests for scripting (the official csi.exe and/or VS interactive window) to support the same nuget package reference syntax that dotnet-script and .NET Interactive support (see dotnet/roslyn#43918 for one such request). Other than this needing to be something the host deals with resolving (the compiler could certainly parse this for the host's benefit, but I doubt the compiler wants to be in charge of actually fetching the nuget packages) I see no reason this should not be supported everywhere the I do have mixed feeling about introducing a third type of csharp mode for this. The simple program language support has already made the scripting and non-scripting a lot more similar than they previously were, yet the scripting language has some "features" that may be undesirable for simple program usage. On the other hand. the whole point here seems to be making it possible to run these files a lot like an interpreted scripting language (python, ruby, etc), including hash bang support, which kind of points in the direction that this really should just be using the scripting language despite its differences from full c#, or perhaps have this be some form of stricter scripting mode that disables some of the undesirable differences. |
@KevinCathcart A key thing, which perhaps isn't expressed well in this document, is that this is not another dialect of C# like the scripting dialect is. It's just C#. Everything here (top-level statements, global There's some more details to write up here, such as also allowing This is in contrast to the scripting dialect, which very much changes C# semantics such as having shadowing and disallowing namespace declarations. This proposal is not about unifying the scripting dialect with C# proper. It's just about pulling in existing and proposed C# features + updating build tooling to allow using them together without a project. |
Making |
Yeah, in a project context they'd likely get ignored, at least that's the current thinking. Any |
Some packages, for example SQLite, need to run msbuild props/targets to work. This is most common for packages that are managed wrappers of native dlls, and the packages support both packages.config as well as PackageReference, hence why they contain msbuild props/targets and not just use NuGet's Maybe this question is too detailed for a high level design, but should these packages work with the single file |
@zivkan that's a good point of consideration. I haven't dived into details like this just yet (maybe that comes later?) but in my head I imagine that an in-memory or temp project file is involved. For example, here's that package working in F# Interactive, which has If a project file is generated behind the scenes (temp or in memory) then other msbuildy things could (in theory?) also work, like .editorconfig plumbing into the compiler, directory.build.props, etc. |
So you are proposing removing the errors for those directives for normal project based compilation to avoid even being a minor dialect from the language POV? (arguable still a minor dialect none-the-less, since you are applying different meaning to those directives then I would get by typing I don't see any discussion of possibly allowing no-op or fully functional #r or #load directive in normal compilation in the LDM notes, so I'm guessing they have not weighed in on if doing that is sensible? Obviously it is trivially possible to implement, but that does not mean it is a good idea. |
It's tentatively on the schedule for next week. Suffice to say that we have a good deal of interest in the idea, as we've been discussing it in various forms (mostly via the top-level statements feature) for a few years now. https://github.com/dotnet/csharplang/tree/main/meetings/2021#may-12-2021 |
|
||
## `dotnet` command support | ||
|
||
Only `dotnet run` and `dotnet build` are supported with Simple C# Programs. All other `dotnet` commands will error out, indicating that you need a project. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dotnet test
would be interesting too. The file could have top-level methods that are unit tests, and dotnet test
would run them.
While working in JavaScript, I found standalone unit test files useful when sharing a minimal repro for a library bug--that's something especially hard to do with .NET today.
Cool. So the question of if this should effectively be a super minor dialect, or if
I also note that .NET Interactive does not currently rely on the compiler parsing the NuGet version of Preprocessing is probably best avoided, since making that work as expected with things like ifdefs is really tricky. On the other hand, for nuget packages that include MSBuild snippets that are required for proper functioning, loading them in the compiler is potentially too late. I'm also not sure if packages including analyzers or source generators would be a problem during compilation, or if those could be successfully added to a compilation already in progress, |
Well, it's been a key driving principle that it's not a dialect of C#. Also, while it's certainly up for discussion, I don't believe anyone has discussed or has intentions of putting a NuGet resolver into the compiler itself: it will almost certainly be a separate tool invoked as part of the pipeline. Whether that tool has differences when invoked as part of a project file or when just running a |
Would a net effect of this also allow something like Source Generators? I could see some interesting applications specifically for using source generators specifically with simple programs. |
Why not support |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding a section about C# compiler error messages, and the expectation for them to be more helpful in context without tooling would also be great.
Some minor comments along the lines.
imho the semantics should be similar to how AssemblyInfo.cs works: a default is generated for you, but you can provide your own if you need to customize it. So if the only thing I need to customize in my project file is:
Then you don't need a project file and those can be inferred for the C# files themselves. This would have the consequence that: dotnet build <some folder> would act as if it were running as dotnet build <some folder>\<some folder>.csproj (assuming only C# files are in that folder, I assume this should error if there are cs/vb/f# files in a directory, same situation as when you run This also has several behavioral fallouts:
I think the advantage of these semantics is it is easy to explain when to use a project file:
NOTE: I am also assuming that any dotnet cli command that operates on projects today would work following this scheme. That would mean:
|
For the same reason, I wouldn't expect While It seems to me the ideal/preference of making all dotnet cli commands work consistently for directories without project files does not line up with the spec's proposal that programs will need to "grow up" to have project files. Otherwise I think this spec should be proposing that project files become optional/obsolete, rather than being only for simple programs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done with review pass (iteration 6)
proposed/simple-csharp-programs.md
Outdated
|
||
Behind the scenes, a likely implementation will involved a synethesized project file. This would then have all of the information to make the `dotnet` commands work, and open us up to allowing more `dotnet` commands in the future. | ||
|
||
A synthezized project file could live either in memory or in the temp folder. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sure that'll come up in next round of discussion with SDK team: we'll want to specify what that project looks like.
I assume the OutputType
would be Exe
, for instance.
```csharp | ||
#r "nuget: Newtonsoft.Json" | ||
|
||
record Person(string Name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: As you mentioned, the record declaration should come after the top-level statements.
Co-authored-by: Fred Silberberg <fred@silberberg.xyz>
For me, I think another possibility is to put it like those .NET v2 "website project", where we have a .CONFIG file provide configurations common to files in folder, all .aspx/,asmx files can be treated as single application, and you can freely reference any addition binaries in bin folder. File location and config file syntax could be rearranged it to make it configuration folder like .git, possibly with simple configuration UI like that of TortoiseGit or IIS management for those less comfortable with editing config files directly. Now when I work on .CS files inside that folder, I can be sure that the basic settings I used to compile to be the same and I don't need to re-specify it every time. |
There is no technical reason the I think it is good to have the discussion about where the "line" is terms of what is supported. I took a position very much on the "most possible things working" side because it is easy to explain. What works? Everything. My internal model is "If you don't need project files you should not require them". Project to project references very much feel like a case where having project files makes things easier. Perhaps a project-less program could reference other projects, I could see the utility of this. But regardless of the technical hurdles I think trying to reference a folder or file instead of a direct project would be error prone. imho we should allow p2p references so long as it is not ambiguous. So a single file referencing projects would be fine.
I don't think the goal is to make them obsolete, just unnecessary for "simple" cases. You used to need to specify AssemblyInfo.cs files, now those are generated for you. You used to need to create
Yes this is a good example. I could imagine want to
My question is how do we tool this so it isn't confusing to users? Why is it more useful for this feature if its only console apps? I agree class libraries working is not very useful. But I assume that users won't do things that are not useful. There is no need to build a wall when a simple guardrail is sufficient. If I have a small file that I just want to ship as a library for a few of my hobby projects why can't
@cartermp can chime in here with his own thoughts. To me "grow up" means "having project files is useful". If having a project file is just a cognitive burden, then I argue that it should be allowed to be omitted. Project files provide real value in many situations but requiring them seems unnecessary. If your code does not require a project file then it is, in my definition, "simple". |
I'll close this one since I don't work on the product anymore and, although I'd like to see this get done, I don't have the time nor energy to see this proposal through to completion. Anyone else who's interested can give it a whirl, though. |
Let's see if we can make C# a little simpler.
Working list of additions/changes to make to the doc: