Nyheter i .NET 7 och C# 11 - Stefan tycker till

Blog Post by Stefan Holmberg

Med en ny version av .NET och dessutom C# uppgraderat till v11 är de stora frågorna:

  • vad är nytt?
  • är det bra saker?
  • ska jag/vi uppgradera?

Jag kommer nedan gå igenom en del av nyheterna och förutom att förklara vad de innebär även ge min personliga syn på hur användbara de är. Observera att detta är personliga åsikter, jag har efter 30 år i branschen strong opinions, och ta också med dig att jag såklart är färgad av mina erfarenheter och tittar ur perspektivet "Line-Of-Business"-applikationer dvs web+backend -> SQL databas (jamen mer eller mindre avancerad CRUD: tänk försäkringssystem, e-commerce etc etc )

OBS jag kommer också förenkla och generalisera en del, men det beror dels på att det är avancerade saker i vissa fall, i andra fall så är det helt enkelt så att jag har inte kunskapen.


.NET 7

Man pratar ju mycket om förbättrad prestanda så här kommer lite sånt.


OSR (on-stack replacement)

Begreppet OSR (on-stack replacement) är ganska galet!

Tänk dig en funktion CalculateTax(...) för 10M personer eller nåt. Vi har en massa if-statements osv och tunga beräkningar. Under körningen kan .NET profilera och se att oj, nu när jag ser HUR datan ser ut och vilka if-satser som är mest använda etc etc, om vi hade optimerat koden på ett annat sätt så hade det blivit snabbare. Och då kan .NET kompilera om med dessa optimeringar och BYTA ut koden under körningens gång!

Alltså jag har aldrig förstått mig på detta - hur är det ens möjligt, men det är inget nytt: det är samma teknik tex som gör att Lucene, ElasticSearch och Solr etc etc kan köra så sjukt snabbt i en JVM - ofta snabbare än C/C++-varianter som ju inte kan OSR:a då.


Native AOT

Native AOT låter dig skapa en self-contained binär (dvs du kompilerar för en specifik plattform), med andra ord du har inte inte bytekod (MSIL). Self-contained, visst, men vi pratar 3.7MB för en HelloWorld-exefil för Windows X64 om jag minns rätt. Vad gör det för skillnad - snabbare startup och mindre RAM-usage.

Nåt för mig? Nej tror inte det...aldrig haft egentliga problem med startup tid


System.Text.Json serialization med typer

Jamen ett kodexempel:

[JsonDerivedType(typeof(HockeyPlayer), 0)]
[JsonDerivedType(typeof(FootballPlayer), 1)]
[JsonDerivedType(typeof(BasketPlayer), 2)]
public class Player
{
    public string Name { get; set; }
    public string City { get; set; }
}

public class HockeyPlayer : Player { public int JerseyNumber { get; set; } }

public class FootballPlayer : Player { public int JerseyNumber { get; set; } public int ShoeSize { get; set; } }

public class BasketPlayer : Player { public int LengthInCentimeter { get; set; } }

public class DemoJson { public void Run() { var players = new List { new BasketPlayer { City = "Stockholm", Name = "Stefan", LengthInCentimeter = 190 }, new HockeyPlayer() { City = "Colorado", Name = "Foppa", JerseyNumber = 21 }, new FootballPlayer() { City = "Stockholm", Name = "Brollan", JerseyNumber = 9, ShoeSize = 42}, }; var json = JsonSerializer.Serialize(players);

    var l = JsonSerializer.Deserialize<List<Player>>(json);
    foreach(var p in l)
        Console.WriteLine(l);
}

}

Som ni kan se så lägger den till en type-property

[{"$type":2,"LengthInCentimeter":190,"Name":"Stefan","City":"Stockholm"},{"$type":0,"JerseyNumber":21,"Name":"Foppa","City":"Colorado"},{"$type":1,"JerseyNumber":9,"ShoeSize":42,"Name":"Brollan","City":"Stockholm"}] 

Gillar jag detta... vet inte faktiskt. Jag kör JsonConvert av gammal vana och där kan man ju

var json = JsonConvert.SerializeObject(players, Formatting.Indented, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.All
}

Generic math

static T Add(T left, T right)
    where T : INumber
{
    return left + right;
}

Whatwever...klarat mig utan detta och gör så i framtiden med


REGULAR EXPRESSIONS

Enormt mycket snabbare etc etc säger dom

Ointresserad...AVOID hursomhelst ju. Finns väl få saker som är så svåra att förvalta som regexpressions. Alltså nu föregår jag min slutsats som kommer nedan, men överlag så förespråkar jag ju KISS (keep it simple stupid), enklaste koden => alla i teamet (och även framtida anställningar) kan förvalta koden.

Det vore nästan bättre för kodkvalitet och förvaltningsorganisationerna ifall man gjorde det så långsamt så det blev oanvändbart (nu överdriver jag, visst använder jag också regular expressions...men så lite det går och bara ENKLA).


dotnet publish -> container

Nu ska man kunna skapa container images (det vissa felaktigt kallar "Docker" images) direkt med dotnet publish

alltså vad är det med Microsoft och att försöka knöka in allt i deras tooling? Alltså jag ser inte problemet med vanliga det flödet för att bygga container images och är inte intresserad av att ha två olika flöden nu, ett för .NET och ett för mina andra applikationer


ASP.NET Core:

Nullable models in MVC Views and Razor Pages

@model Product?

aldrig haft problem med detta


Minimal APIs

Klart förbättrat gällande filters etc etc

Jag ser inte poängen med minmal API:s överhuvudtaget. "Härma" django/expressjs/etc var väl hur det började och det är inte DÄR programmeringskomplexiteten ligger. I vårt dagliga arbete menar jag.


SignalR

har nu Dependency injection för Hub constructorn. Visst jättebra...men en ganska smal sak


Blazor

ja....massa nya saker där men det är ju för att produkten i sig är ung och inte speciellt feature-rich som den är nu. Jag avvaktar...vill nog se att Blazor lyfter...


HTTP/2 performance improvements

nu pratar vi nörderi. Kestral (den inbyggda http-servern som används i våra webbapplikationer) har förbättrat throughput för multiplexade connections (förenklat tänk dig ett anrop till en html-sida - den kommer ju sannolikt att göra många anrop till samma server: för att hämta css/images etc etc)

Inget jag testat att det verkligen gör skillnad, men bara genom att läsa att man ändrat från locks (motsvarande "critical sections") till en kö gör att man förstår att CPU resurser kommmer slösas i mindre utsträckning


C# 11

Generic attributes.

Alla "whats new" sajter har med detta. Fast ingen kan visa på ett vettigt use-case...Stefan is NOT interested

Raw string literals

Också med på alla... just detta exempel

string longMessage = """
    This is a long message.
    It has several lines.
        Some are indented
                more than others.
    Some should start at the first column.
    Some have "quoted text" in them.
    """;

Jaha...


Required member

public class BasketPlayer : Player
{
    public int LengthInCentimeter { get; set; }
    public required string Position { get; set; }
}

Nu kan du inte

            new BasketPlayer { City = "Stockholm", Name = "Stefan", LengthInCentimeter = 190 },

Utan den säger

Error	CS9035	Required member 'BasketPlayer.Position' must be set in the object initializer or attribute constructor.	

I LOVE IT !!!! Jag som utbildare förespråkar ju proper use av constructors, alltid säkerställa valid state. Men object initializer vill man ju ofta köra


File scopade data types

--------------------
// In File1.cs:
file class HiddenWidget
{
    public int Work() => 42;
}

Jag gillar tänket kring module-scopes osv som man ser i Python och Go. Men vet ännu inte om jag egentligen behöver det. Kodgeneratorer nämns ju som ett självklar usecase där man enkelt undviker name collisions

LIST Patterns

Jag kommer här bara visa och prata om jämförelser

    int[] nummer = { 1, 2, 3, 5 };
    if (nummer is [_, _, 3, _]) //2 whatever, sen en trea sen en   whatever
    {
        Console.WriteLine("Samma");
    }

    if (nummer is [.., 5])  // SLUTAR MED EN FEMMA
    {
        Console.WriteLine("Samma");
    }

Gillar jag detta? Vet inte...Här har vi återigen en sån sak som kommer att göra att kodbaserna ute på företagen kommer se mer och mer olika ut. Standards, konsekvent syntax. Såna saker (som gör att det är "enkelt" för nya att komma in och koda) värderar företagen mer än cool kod.

Herregud vad är fel på:

        if (nummer.Length == 4 && nummer[2] == 3)
        if (nummer.Length  >= 1 && nummer[nummer.Length-1] == 5)

Ska jag uppgradera?

Ja. Vare sig "behöver" nya features eller inte så är det ju det bara att åka med. Vi vill absolut inte stå med applikationer byggda med ett ramverk som inte längre stödjs (tex pre Core 3.1 just nu då)

Är det stora saker som behöver göras? Sannolikt inte men kolla in Breaking changes https://learn.microsoft.com/en-us/dotnet/core/compatibility/7.0


Vart är vi på väg, Stefans rants:

Jag låter nog som en gammal gubbe, och det tar jag varje dag i veckan. Ute på företag tar jag gärna rollen som den konservative - jag älskar cool teknik, det är inte det - men en stor del i vårt uppdrag är just att säkerställa modifierbar/konsekvent kod i hela applikationens livscykel.

Det är lätt att bli carried away och betrakta sin kod som något mer än vad det är. Det kan visst vara vackert, det kan vara poesi.

Min kod är det. Eller jag försöker skapa poesi med min kod

Men kod som inte är min - dvs FÖRETAGETS gäller att

Jag har lite svårt för många av nyheterna här: det Microsoft gör (enligt mig) är att man lyssnar FÖR MYCKET (är det möjligt?) på communityt. Visst ska man lyssna, men med en uttalad plan för C# att den som programmerar C# ska behöva "skriva så få rader som möjligt" (yes, jag läser det på jättemånga microsoft-bloggar just nu angående csharp 11) så tycker jag man siktar fel. Andra språk har som mål att "det ska bara finnas ETT sätt att göra saker på" (Go) eller att verkligen vara slow moving för Enterprise-företag ska kunna ha långsiktighet i kunskapsförsörjning etc (Java)

Det Microsoft riskerar vara på väg emot är ytterligare en BLOAT-återvändsgränd som med .NET Framework och en total omskrivning inom...ja who knows?

Rekommenderade kurser inom detta ämne

.

Webutvecklare.NET
© Copyright Systementor AB. All Rights Reserved
Version: 1.0.20240904.1-74e3242