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
- nåt som ska fungera och skapa affärsvärden för ditt företag
- och det ska gå att förändra applikationen i framtiden
- företagets framtida kompetensförsörjning är ju en faktor att ha med
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?