We are delighted to release .NET 6 Preview 7. It is the last preview before we enter the (two) Release Candidate (RC) period. The team has been burning the midnight oil and the candle at both ends getting the last set of features in before we slow the speed down on the release. It’s also the release where you will see the last bit of polish on various features and large it-took-the-whole-release features come in all at once. From this point, the team will be focused on bringing all the features to uniform (high) quality so that .NET 6 is ready for your production workloads.
On the topic of production workloads, it’s worth reminding everyone that both the .NET website and Bing.com have been running on .NET 6 since Preview 1. We’re in talks with various teams (Microsoft and otherwise) about going into production with the .NET 6 RCs. If you are interested in that and want guidance on how to approach that, please reach out at dotnet@microsoft.com. We’re always happy to talk to early adopters.
You can download .NET 6 Preview 7 for Linux, macOS, and Windows.
- Installers and binaries
- Container images
- Linux packages
- Release notes
- API diff
- Known issues
- GitHub issue tracker
See the .NET MAUI and ASP.NET Core for more detail on what’s new for client and web application scenarios.
.NET 6 Preview 7 has been tested and is supported with Visual Studio 2022 Preview 3. Visual Studio 2022 enables you to leverage the Visual Studio tools developed for .NET 6 such as development in .NET MAUI, Hot Reload for C# apps, new Web Live Preview for WebForms, and other performance improvements in your IDE experience. .NET 6 is also supported with Visual Studio Code. The latest version of the C# extension for Visual Studio Code has been updated for .NET 6 Preview 7 and includes support for C# 10.
Check out the new conversations posts for in-depth engineer-to-engineer discussions on the latest .NET features. We also published posts on String Interpolation in C# 10 and .NET 6 Preview Features in .NET 6 – Generic Math.
.NET SDK: C# project templates modernized
We updated .NET SDK templates to use the latest C# language features and patterns. We hadn’t revisited the templates in terms of new language features in a while. It was time to do that and we’ll ensure that the templates use new and modern features going forward.
The following language features are used in the new templates:
- Top-level statements
- async Main
- Global using directives (via SDK driven defaults)
- File-scoped namespaces
- Target-typed new expressions
- Nullable reference types
You might wonder why we enable certain features via templates instead of enabling them by default when a project targets .NET 6. We’re OK with requiring some amount of work on your part to upgrade applications to a new version of .NET as a tradeoff for improving the default behavior of the platform. This allows us improve the product without complicating project files over time. However, some features can be quite disruptive with that model, such as nullable reference types. We don’t want to tie those features to the upgrade experience, but want to leave that choice to you, both when and if ever. The templates are a much lower risk pivot point, where we’re able to set what the new “good default model” is for new code without nearly as much downstream consequence. By enabling these features via project templates, we’re getting the best of both worlds: new code starts with these features enabled but existing code isn’t impacted when you upgrade.
Console template
The console
template demonstrates the biggest change. It’s now (effectively) a one-liner by virtue of top-level statements and global using directives.
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
The .NET 5 version of the same template includes several lines of familiar ceremony that provide the structure previously necessary for even a single line of actual code.
using System;
namespace Company.ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
}
}
}
The project file for the console
template has also changed, to enable the nullable reference types feature, as you can see in the following example.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
Other templates also enable nullability, implicit global usings, and file scoped namespaces, including ASP.NET Core and Class Library.
ASP.NET web template
The web
template is also similarly reduced in lines of code, using the same features.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.MapGet("/", () => "Hello World!");
app.Run();
ASP.NET MVC template
The mvc
template is similar in structure. In this case, we’ve merged Program.cs
and Startup.cs
into a single file (Program.cs
), creating a further simplification.
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
Template compatibility
See the following documents for compatibility concerns with using the new templates.
Libraries: Reflection APIs for nullability information
Nullable reference types is an important feature for writing reliable code. It works great for writing code but not (until now) for inspecting it. New Reflection APIs enable you to determine the nullability nature of parameters and return values for a given method. These new APIs will be critical for Reflection-based tools and serializers, for example.
For context, we added nullable annotations to the .NET Libraries in .NET 5 (and finished up in .NET 6) and are in the process of doing same with ASP.NET Core this release. We also see developers adopting nullability for their projects.
Nullability information is persisted in metadata using custom attributes. In principle, anyone can already read the custom attributes, however, this is not ideal because the encoding is non-trivial to consume.
The following examples demonstrate using the new APIs for a couple different scenarios.
Getting top-level nullability information
Imagine you’re implementing a serializer. Using these new APIs the serializer can check whether a given property can be set to null
:
private NullabilityInfoContext _nullabilityContext = new NullabilityInfoContext();
private void DeserializePropertyValue(PropertyInfo p, object instance, object? value)
{
if (value is null)
{
var nullabilityInfo = _nullabilityContext.Create(p);
if (nullabilityInfo.WriteState is not NullabilityState.Nullable)
{
throw new MySerializerException($"Property '{p.GetType().Name}.{p.Name}'' cannot be set to null.");
}
}
p.SetValue(instance, value);
}
Getting nested nullability information
Nullability has special treatment for objects that can (formally) hold other objects, like arrays and tuples. For example, you can specify that an array object (as a variable, or as part of a type member signature) must be non-null but that the elements can be null, or vice versa. This extra level of specificity is inspectable with the new Reflection APIs, as you see demonstrated in the following example.
class Data
{
public string?[] ArrayField;
public (string?, object) TupleField;
}
private void Print()
{
Type type = typeof(Data);
FieldInfo arrayField = type.GetField("ArrayField");
FieldInfo tupleField = type.GetField("TupleField");
NullabilityInfoContext context = new ();
NullabilityInfo arrayInfo = context.Create(arrayField);
Console.WriteLine(arrayInfo.ReadState); // NotNull
Console.WriteLine(arrayInfo.Element.State); // Nullable
NullabilityInfo tupleInfo = context.Create(tupleField);
Console.WriteLine(tupleInfo.ReadState); // NotNull
Console.WriteLine(tupleInfo.GenericTypeArguments [0].State); // Nullable
Console.WriteLine(tupleInfo.GenericTypeArguments [1].State); // NotNull
}
Libraries: ZipFile Respects Unix File Permissions
The System.IO.Compression.ZipFile
class now captures Unix file permissions during create and set file permissions when extracting zip archives on Unix-like operating systems. This change allows for executable files to be round-tripped through a zip archive, which means you no longer have to modify file permissions to make files executable after extracting a zip archive. It also respects the read/write permissions for user
, group
, and other
as well.
If a zip archive doesn’t contain file permissions (because it was created on Windows, or using a tool which didn’t capture the permissions, like an earlier version of .NET) extracted files get the default file permissions, just like any other newly created file.
The Unix file permissions work with other zip archive tools as well, including:
Early .NET 7 Feature Preview: Generic Math
For .NET 6, we’ve built the capability to mark APIs as “in preview”. This new approach will allow us to offer and evolve preview features across multiple major releases. In order to use preview APIs, projects need to explicitly opt-into using preview features. If you use preview features without explicitly opting-in, you will see build errors with actionable messages, starting in .NET 6 RC1. Preview features are expected to change, likely in breaking ways, in later releases. That’s why they are opt-in.
One of those features we’re previewing in .NET 6 is static abstract interface members. Those allow you to define static abstract methods (including operators) in interfaces. For example, it is now possible to implement algebraic generic methods. For some folks, this feature will be the absolute standout improvement we’re delivering this year. It is perhaps the most important new type system capability since Span<T>
.
The following example takes an IEnumerable<T>
and is able to sum all the values due to the T
being constrained to INumber<T>
, possibly an INumber<int>
.
public static T Sum<T>(IEnumerable<T> values)
where T : INumber<T>
{
T result = T.Zero;
foreach (var value in values)
{
result += value;
}
return result;
}
This works because INumber<T>
defines various (static) operator overloads that must be satisfied by interface implementors. The IAdditionOperators
is perhaps the easiest new interface to understand, which INumber<T>
itself is derived from.
This is all powered by a new feature which allows static abstract
members to be declared in interfaces. This enables interfaces to expose operators and other static methods, such as Parse
or Create
, and for those to be implemented by a derived type. Please see our associated blog post for more details!
All of the features mentioned are in preview for .NET 6 and not supported for use in production. We would appreciate your feedback using them. We intend to continue evolving and improving the generic math features and the runtime and C# features that support them in .NET 7. We expect to make breaking changes to the current experience, and that’s part of the reason why the new APIs are marked as “in preview”.
Libraries: NativeMemory APIs
We added new native memory allocation APIs exposed via System.Runtime.InteropServices.NativeMemory
. These APIs represent equivalents to the malloc
, free
, realloc
, and calloc
C APIs and also includes APIs for doing aligned allocations.
You may be wondering about how to think about these APIs. First, they are low-level APIs that are intended for low-level code and algorithms. Application developers would rarely if ever use these. Another way to think about these APIs is similarly to the platform intrinsic APIs, which are low-level .NET APIs for chip instructions. These APIs are similar but expose low-level APIs for memory-related operations.
Libraries: System.Text.Json serialization notifications
The System.Text.Json serializer now exposes notifications as part of (de)serialization operations. They are useful for defaulting values and validation. To use them, implement one or more of the interfaces IJsonOnDeserialized
, IJsonOnDeserializing
, IJsonOnSerialized
or IJsonOnSerializing
within the System.Text.Json.Serialization
namespace.
Here’s an example that validates during both JsonSerializer.Serialize()
and JsonSerializer.Deserialize()
to ensure a FirstName
property is not null
.
public class Person : IJsonOnDeserialized, IJsonOnSerializing
{
public string FirstName{ get; set; }
void IJsonOnDeserialized.OnDeserialized() => Validate(); // Call after deserialization
void IJsonOnSerializing.OnSerializing() => Validate(); // Call before serialization
private void Validate()
{
if (FirstName is null)
{
throw new InvalidOperationException("The 'FirstName' property cannot be 'null'.");
}
}
}
Previously, you would need to implement a custom converter to achieve this functionality.
Libraries: System.Text.Json serialization property ordering
We’ve also added the ability to control the serialization order of properties, with System.Text.Json.Serialization.JsonPropertyOrderAttribute
. An integer specifies the order. Smaller integers are serialized first; properties that have no attribute have a default ordering value of 0.
Here’s an example that specifies JSON should be serialized in the order Id, City, FirstName, LastName
:
public class Person
{
public string City { get; set; } // No order defined (has the default ordering value of 0)
[JsonPropertyOrder(1)] // Serialize after other properties that have default ordering
public string FirstName { get; set; }
[JsonPropertyOrder(2)] // Serialize after FirstName
public string LastName { get; set; }
[JsonPropertyOrder(-1)] // Serialize before other properties that have default ordering
public int Id { get; set; }
}
Previously, the serialization order was determined by reflection order which was neither deterministic nor resulting in a specific desired order.
Libraries: “write raw” JSON with System.Text.Json.Utf8JsonWriter
There are times when you need to integrate “raw” JSON when writing JSON payloads with Utf8JsonWriter.
For example:
- I have a deliberate sequence of bytes I want to write out on the wire, and I know what I’m doing (as demonstrated in the following example).
- I have a blob which I think represents JSON content and which I want to envelope, and I need to make sure the envelope & its inner contents remain well-formed
JsonWriterOptions writerOptions = new() { WriteIndented = true, };
using MemoryStream ms = new();
using UtfJsonWriter writer = new(ms, writerOptions);
writer.WriteStartObject();
writer.WriteString("dataType", "CalculationResults");
writer.WriteStartArray("data");
foreach (CalculationResult result in results)
{
writer.WriteStartObject();
writer.WriteString("measurement", result.Measurement);
writer.WritePropertyName("value");
// Write raw JSON numeric value using FormatNumberValue (not defined in the example)
byte[] formattedValue = FormatNumberValue(result.Value);
writer.WriteRawValue(formattedValue, skipValidation: true);
writer.WriteEndObject();
}
writer.WriteEndArray();
writer.WriteEndObject();
The following is a description of what the code above — particularly FormatNumberValue
— is doing. For performance, System.Text.Json
omits the decimal points/values when the number is whole, like 1.0
. The rationale is that writing fewer bytes is good for perf. In some scenarios, it might be important to retain decimal values because the consumer treats numbers without decimals as integers, otherwise as doubles. This new “raw value” model allows you to have that level of control wherever you need it.
Libraries: Synchronous stream overloads on JsonSerializer
We’ve added new synchronous APIs to JsonSerializer
for serializing and deserializing JSON data to/from a stream. You can see that demonstrated in the following example.
using MemoryStream ms = GetMyStream();
MyPoco poco = JsonSerializer.Deserialize<MyPoco>(ms);
These new synchronous APIs include overloads that are compatible and usable with the new System.Text.Json source generator, by accepting JsonTypeInfo<T>
or JsonSerializerContext
instances.
Libraries: System.Text.Json.Nodes.JsonNode support for dynamic
is removed
Support for the C# dynamic
type in the JsonSerializer has been removed. We added dynamic
support in Preview 4 but later decided to be a poor design choice, including making it a required dependency of the JsonNode
type.
This change is considered a breaking change from a .NET 6 preview to preview standpoint but not from .NET 5 to 6.
Libraries: System.Diagnostics Propagators
We’ve been improving support for OpenTelemetry over the last couple years. One of the key aspects of enabling great support is ensuring that all components that need to participate in telemetry production produce network headers in the right format. It’s really hard to do that, particularly as the OpenTelemetry specification changes. OpenTelemetry defines the propagation concept to help with this situation. We’re in the process of adopting propagation to enable a general model for header customization.
Context on the broader concepts:
- OpenTelemetry specification — In-memory representation of the distributed tracing data structures.
- OpenTelemetry Span — Building block for a trace, and represented by System.Diagnostics.Activity in .NET.
- W3C TraceContext — Spec on how to propagate these distributed tracing data structures over well-know HTTP headers.
The following code demonstrates the general approach for using propagation.
DistributedContextPropagator propagator = DistributedContextPropagator.Current;
propagator.Inject(activity, carrier, (object theCarrier, string fieldName, string value) =>
{
// Extract the context from the activity then inject it to the carrier.
});
You can also choose to use a different propagator.
// Set the current propagation behavior to not transmit any distributed context information in outbound network messages.
DistributedContextPropagator.Current = DistributedContextPropagator.CreateNoOutputPropagator();
The DistributedContextPropagator
abstract class determines if and how distributed context information is encoded and decoded as it traverses the network. The encoding can be transported over any network protocol that supports key-value string pairs. DistributedContextPropagator
inject values into and extracts values from carriers as key/value string pairs.
By adding support for propagators, we’ve enabled two things:
- You’re no longer required to use the W3C TraceContext headers. You can write a custom propagator (i.e., use your own headers names including not sending them at all) without the libraries HttpClient, ASP.NET Core having a priori knowledge of this custom format
- If you implement a library with a custom transport (e.g., message queue), you can now support various wire formats as long as you support sending and receiving a text map (e.g.
Dictionary<string, string>
)
Most application code does not need to directly use this feature, however, it is likely that you will see it in a call-stack if you use OpenTelemetry. Some library code will want to participate in this model if it cares about tracing and causality.
Libraries: Simplified call patterns for cryptographic operations
The .NET encryption and decryption routines were designed around streaming, with no real concept for defining when the payload is already in memory. The new Encrypt- and Decrypt- methods on SymmetricAlgorithm
accelerate the already-in-memory case, and are intended to provide clarity to the caller and the code reviewer. Additionally, they support reading from and writing to spans.
The new simplified methods offer a straightforward approach to using cryptographic APIs:
private static byte[] Decrypt(byte[] key, byte[] iv, byte[] ciphertext)
{
using (Aes aes = Aes.Create())
{
aes.Key = key;
return aes.DecryptCbc(ciphertext, iv);
}
}
With the new Encrypt- and Decrypt-methods, only the key property is used from the SymmetricAlgorithm instance. The new DecryptCbc method supports choosing the padding algorithm, but PKCS#7 is used with CBC so often that it’s a default argument. If you like the clarity, just specify it:
private static byte[] Decrypt(byte[] key, byte[] iv, byte[] ciphertext)
{
using (Aes aes = Aes.Create())
{
aes.Key = key;
return aes.DecryptCbc(ciphertext, iv, PaddingMode.PKCS7);
}
}
You can see that the existing pattern — with .NET 5 — required significantly more plumbing for the same outcome.
private static byte[] Decrypt(byte[] key, byte[] iv, byte[] ciphertext)
{
using (Aes aes = Aes.Create())
{
aes.Key = key;
aes.IV = iv;
// These are the defaults, but let's set them anyways.
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
using (MemoryStream destination = new MemoryStream())
using (ICryptoTransform transform = aes.CreateDecryptor())
using (CryptoStream cryptoStream = new CryptoStream(destination, transform, CryptoStreamMode.Write))
{
cryptoStream.Write(ciphertext, 0, ciphertext.Length);
cryptoStream.FlushFinalBlock();
return destination.ToArray();
}
}
}
Libraries: Full Case Mapping Support in Globalization Invariant Mode
Globalization Invariant Mode enables you to remove application dependencies on globalization data and behavior in exchange for smaller applications (primarily on Linux). We’ve improved Globalization Invariant Mode to support case mapping of the full Unicode character set. Previously, this mode only supported ASCII range characters for operations like String.ToUpper
, String.ToLower
, and string comparisons and searching with the IgnoreCase option.
Alpine-based .NET container images are the only environment where we enable globalization environment mode by default.
Runtime: W^X (write xor execute) support for all platforms and architectures
The runtime now has a mode in which it doesn’t create or use any memory pages that are writeable and executable at the same time. All executable memory is mapped as read-execute only. This feature was enabled on macOS — for Apple Silicon — earlier in the release. On Apple Silicon machines, memory mappings that are writeable and executable at the same time are prohibited.
This capability is now enabled and supported on all other platforms as an opt-in experience. On these platforms, executable code generation / modification is done via separate read-write memory mappings. This is true for both JIT’d code and runtime-generated helpers. These mappings are created at virtual memory addresses that are different from the executable code address and exist only for a very brief period of time when the writing is performed. For example, the JIT now generates code into a scratch buffer that is copied into the executable memory using a single memory copy function call after the whole method is jitted. And the writeable mapping lifetime spans only the time of the memory copy.
This new feature can be enabled by setting the environment variable DOTNET_EnableWriteXorExecute
to 1
. This feature is opt-in in .NET 6 because it has a startup regression (except on Apple Silicon). The regression is ~10% in our ASP.Net benchmark tests when compiled with Ready To Run (R2R). However, the steady state performance was measured to be the same with and without the feature enabled. For applications where startup performance isn’t critical, we recommend enabling this feature for the improved security that it offers. We intend to resolve the performance regression as part of .NET 7 and enable the feature by default at that time.
Runtime: CodeGen changelog
The following changes were made in code generation in Preview 7.
Community PRs
The following PRs were all from @SingleAccretion:
- OptimizeÂ
CAST(int <- long)
 on 32 bit targets runtime#53040 - Eliminate chained casts to small types runtime#52561
- Remove some unneeded code from division morphing runtime#53464
- Fix CQ regression & correctness bug in morphing of long muls runtime#53566
- Do not eliminate casts from FP types when optimizing narrow stores runtime#53667
- Move the “do not zero-extend setcc” optimization to lower runtime#53778
- Disable folding of implementation-defined casts runtime#53782
- Add args descriptions for VNF_MapStore and VNF_MapSelect runtime#54108
- ImportÂ
cgt.un(op, 0)
 asÂNE(op, 0)
 runtime#54539 - Use local assertion prop to omit casts on returns runtime#55632
Dynamic PGO
The following PRs support the dynamic PGO project.
- [JIT] Improve inliner: new heuristics, rely on PGO data runtime#52708
- Inliner: Extend IL limit for profiled call-sites, allow inlining for switches. runtime#55478
- JIT: enable GDV when static class deduction fails. runtime#55660
LSRA
The following PRs support the LRSA project.
- Spill single-def variable at definition to avoid further spilling runtime#54345
- Mark vars as do not enreg earlier in minopts. runtime#54998
Loop Optimization
The following PRs improve loop optimization.
- Improve loop cloning, with debugging improvements runtime#55299
- Support cloning loops with array of struct indexing expressions runtime#55612
- Increase max loops optimized by RyuJIT from 16 to 64. runtime#55614
Structs
The following PRs improve struct handling.
- Enregister structs on win x64. runtime#55045
- Enreg structs x86 windows. runtime#55535
- Enable StructEnreg by default on all platforms. runtime#55558
- ImproveÂ
TryTransformStoreObjAsStoreInd
 optimization. runtime#55727
Optimizations
The following PRs provide general optimizations.
- “==0” optimization in Boolean logic #13573Â runtime#49548
- Allow implicit widenings when tailcalling runtime#54864
Contributor Showcase
We’re coming — as mentioned multiple times — to the end of the release. We thought we’d take a few moments to showcase some community contributors who have been significant contributions. There are many folks who have contributed significantly. The following folks were nominated for this showcase from a few folks on the team. We can continue with this showcase section if people like it.
The text is written in the contributor’s own words.
Andrii Kurdiumov (@kant2002)
I’m Andrii Kurdiumov, and I’m living in Almaty, Kazakhstan. By trade I work on building new products in enterprise space.
I decided to contribute to .NET because I see opportunities to enter new markets with new MS technologies. Blazor WebAssembly and .NET on Raspberry are working well, but I fear these technologies can break under extreme or unusual requirements. So I decided to invest a bit of my time and check if NativeAOT can help me. So far, my contributions mostly centered around NativeAOT project, even WinForms one. And for some time I plan to follow that direction.
Those were the reasons why I started contributing. Reasons why I continue contributing are the following: I constantly feel support from people working on .NET, I know that they have a lot of experience in the vast areas of software dev. And people working around .NET care a great deal about high quality standards and that immediately set the tone for anybody around. I personally like these kinds of environments.
SingleAccretion
I am an aspiring young programmer, from, as surprisingly many of us .NET people are, Russia. As a person writing code, I’ve started with .NET and progressively went from the higher layers of the stack to lower ones, ending up working on the compiler, just at the edge of the void that is the VM :), . It is a rather fascinating kind of activity, understanding the system as complex and old as RyuJit, but that is also its unique draw, I suppose, at least for curious people like myself.
However, that is not the reason why I contribute to .NET, after all, I could’ve just started my own fork. I think it would be fair of me to say, having waded through so many GH threads throughout these months, that is not at any place one can see people with such deep and rich understanding of the problems in our field. Becoming part of this community, and being able to reason the problems that are reasoned about in it, is something I truly treasure.
Closing
We’re at that point in the release where we consider new features and improvements done. Nice work, team. That’s a wrap on another season of .NET previews.
We continue to want and rely on your feedback. We will focus the rest of .NET 6 on regressions (functional and performance) and bugs found in the new features. Functional improvements in most cases will need to wait for .NET 7. Please share any and all feedback you have and we’ll be happy to categorize it.
Thanks for everyone who has contributed to making .NET 6 another great release.
Thanks for being a .NET developer.
I’m having a weird issue after going from .NET 5 to this preview, where my Inputfile will timeout my app, if i try to upload more than 100KB
Adding to the other comments - I also would like to add the opinion that the oversimplified templates for projects are a step backward for real programming world and also for learners (but they start to notice it only when something goes wrong with their code).
The global usings and top-level statements in project templates are only a "cool" feature to attract newbie programmers into C# because it looks like Node.JS or Python.
But...
I agree 100%
The least they could do is have the old or new templates available through an option
e.g.
dotnet new console (creates the top-level template)
dotnet new console –expert (creates the old style template)
Having no "main method" is useful for scripts and azure functions, but that's a huge drawback for regular projects.
I took a look at the code Richard provided (https://github.com/dotnet/iot/blob/main/src/devices/Pn532/samples/Program.cs) and it is has several readability issues for not having a main method.
I gotta agree with all the other folks here asking for the template to include this back.
I get that removing the namespace and class is 99% of the time good, as your...
Is there an article, page or something that can explain everything that is new and of interest in .net 6 all-up (not just this latest preview release)? I’ve not touched new .net for a while (probably since core 3.1) and want to ramp-up on what is new.
Just created fresh C# console project. I don’t have a single using namespace in my code but I can reach Path, Thread, HttpClient and other classes that should be irrelevant if I’m not using them. Is that a new feature or I just stumbled on a bug?
This is due to the new “global usings”. Please check first comment of this post to see how to disable it if you don’t want it.
@Rich Lander and @schbaem,
Hello, I work for a small company where we like to give our customers the freedom to take like a Grid or a Table and fill out this table with usually: ints, doubles and string parameters, and the code behind is generated, where we do not interact with Xaml at all.
We used to have this capability with the older Windows Form technology and Visual Studio 2010, but for some reason now, Microsoft...
I'm thrilled by the new "minimal" templates and features - huge thanks to the people on the .NET team who made this happen!
This moves us toward a .NET that requires radically less ceremony and boilerplate, which I think is both more approachable for beginners and more convenient for experts. I've already been able to use the new ASP.NET minimal hosting APIs to dramatically simplify a fairly advanced scenario.
This feels like a huge step in the...
As I said these new templates make me more confused. I am not expert and not beginner and I think it is better to explicitly use Program class and Main method than writing top-level statements.
Is there a way to revert back to the VS2022 Preview 2? I’m not really a fan of the new templates and i want the old ones back. From reading other comments i see there is not effort to make an option to bring back the old templates, so is there a way to download the older version?
Stick to Visual Studio 2019 and never upgrade to Visual Studio 2022 cause the previews have shelf life and once dotnet 6 has got to GA, forget it.
I hope templates will be back because these new ones seem to be bad design.
Hi!
I study CS and I tried several different programming languages, frameworks, libraries etc. I am not expert but I want to give some feedback. I hope my opinion would be valuable for you.
I was intersted in learning .NET/C# because of open source, cross-platform (Linux yeah), OOP, typed language, performance and so on. I started few months ago - from time to time I just casually read and watch some random stuff on Internet. Also I...
Where can we find the global usings declared in the Web API template?