Prägnanter Code mit C# 10
Seite 4: Listings
Listing 1: Autor.cs
01: using System.Runtime.CompilerServices;
02:
03: // File-Scoped Namespaces
04: namespace Heise.Developer;
05:
06: // Readonly Record Struct auf dem Stack
07: public readonly record struct Autor(int ID,
08: string Name,
09: string Artikelstatus = "unbekannt")
10: {
11: public readonly DateOnly ObjektErzeugungsZeitpunkt { get; }
12: = new DateOnly(2006, 6, 1);
13:
14: // Methode mit Caller Argument Expression
15: public void CheckObjektErzeugungsZeitpunkt
16: (DateOnly yearMin, DateOnly yearMax,
17: [CallerArgumentExpression("yearMin")] string?
18: yearMinExpression = null,
19: [CallerArgumentExpression("yearMax")] string?
20: yearMaxExpression = null)
21: {
22: if (ObjektErzeugungsZeitpunkt < yearMax ||
23 ObjektErzeugungsZeitpunkt > yearMax)
24: {
25: throw new ArgumentOutOfRangeException(
26: nameof(ObjektErzeugungsZeitpunkt),
27: $"{ObjektErzeugungsZeitpunkt} muss zwischen" +
28: $"{yearMin} ({yearMinExpression}) und {yearMax}" +
29: $"({yearMaxExpression}) liegen!");
30: }
31: }
32: }
Listing 2: Program.cs
01: // Global Using Directives
02: global using System;
03: global using static System.Console;
04: using Heise.Developer;
05:
06: WriteLine("C# 10 Demo f�r heise Developer");
07:
08: // Constant interpolated Strings
09: const string Vorname = "Holger";
10: const string Nachname = "Schwichtenberg";
11: const string GanzerName = $"Dr. {Vorname} {Nachname}";
12:
13: // Readonly Record Struct instanzieren
14: var hs1 = new Autor(123, GanzerName);
15: // unm�glich, weil readonly: hs1.Artikelstatus = "abgegeben";
16:
17: // Ver�nderten Klon erstellen
18: var hs2 = hs1 with { Artikelstatus = "abgegeben" };
19: WriteLine(hs2);
20:
21: // Mixed Deconstruction
22: int id;
23: (id, string name, _) = hs2;
24: WriteLine($"Autor #{id}: {name}");
25:
26: // Extended Property Pattern
27: object o = hs2;
28: if (o is Autor { ObjektErzeugungsZeitpunkt.Year: 2006 })
29: {
30: WriteLine("Jahr des ersten Blog-Eintrags stimmt!");
31: }
32:
33: // Aufruf der Methode mit Caller Argument Expression
34: hs2.CheckObjektErzeugungsZeitpunkt(new DateOnly(1996,4,17),
35: DateOnly.FromDateTime(DateTime.Now));
36: // Funktion via Lambda mit Typherleitung deklarieren
37: var status = (Autor a) => "Artikel von " + a.Name +
38: " ist im Status " + a.Artikelstatus;
39: // Funnktion verwenden
40: WriteLine(status(hs2));
Listing 3: Vom Compiler generierten Code für die Record-Struktur in Listing 2
Die Umbrüche wurden zum Teil zugunsten der Lesbarkeit angepasst.
// Heise.Developer.Autor
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
using Heise.Developer;
public readonly struct Autor : IEquatable<Autor>
{
��public int ID { get; init; }
��public string Name { get; init; }
��public string Artikelstatus { get; init; }
��public DateOnly ObjektErzeugungsZeitpunkt { get; }
��public Autor(int ID, string Name,
string Artikelstatus = "unbekannt")
��{
����this.ID = ID;
����this.Name = Name;
����this.Artikelstatus = Artikelstatus;
����ObjektErzeugungsZeitpunkt = new DateOnly(2006, 6, 1);
��}
��public void CheckObjektErzeugungsZeitpunkt(
DateOnly yearMin, DateOnly yearMax,
[CallerArgumentExpression("yearMin")] string?
yearMinExpression = null,
[CallerArgumentExpression("yearMax")] string?
yearMaxExpression = null)
��{
����if (ObjektErzeugungsZeitpunkt < yearMax ||
ObjektErzeugungsZeitpunkt > yearMax)
����{
������DefaultInterpolatedStringHandler
defaultInterpolatedStringHandler =
new DefaultInterpolatedStringHandler(34, 5);
������defaultInterpolatedStringHandler.AppendFormatted(
ObjektErzeugungsZeitpunkt);
������defaultInterpolatedStringHandler.AppendLiteral(
" muss zwischen ");
������defaultInterpolatedStringHandler.AppendFormatted(yearMin);
������defaultInterpolatedStringHandler.AppendLiteral(" (");
������defaultInterpolatedStringHandler.AppendFormatted(
yearMinExpression);
������defaultInterpolatedStringHandler.AppendLiteral(") und ");
������defaultInterpolatedStringHandler.AppendFormatted(yearMax);
������defaultInterpolatedStringHandler.AppendLiteral(" (");
������defaultInterpolatedStringHandler.AppendFormatted(
yearMaxExpression);
������defaultInterpolatedStringHandler.AppendLiteral(")
liegen!");
������throw new ArgumentOutOfRangeException(
"ObjektErzeugungsZeitpunkt",
defaultInterpolatedStringHandler.ToStringAndClear());
����}
��}
��public override string ToString()
��{
����StringBuilder stringBuilder = new StringBuilder();
����stringBuilder.Append("Autor");
����stringBuilder.Append(" { ");
����if (PrintMembers(stringBuilder))
����{
������stringBuilder.Append(' ');
����}
����stringBuilder.Append('}');
����return stringBuilder.ToString();
��}
��private bool PrintMembers(StringBuilder builder)
��{
����builder.Append("ID = ");
����builder.Append(ID.ToString());
����builder.Append(", Name = ");
����builder.Append((object?)Name);
����builder.Append(", Artikelstatus = ");
����builder.Append((object?)Artikelstatus);
����builder.Append(", ObjektErzeugungsZeitpunkt = ");
����builder.Append(ObjektErzeugungsZeitpunkt.ToString());
����return true;
��}
��public static bool operator !=(Autor left, Autor right)
��{
����return !(left == right);
��}
��public static bool operator ==(Autor left, Autor right)
��{
����return left.Equals(right);
��}
��public override int GetHashCode()
��{
����return ((
EqualityComparer<int>.Default.GetHashCode(ID) *
-1521134295 +
EqualityComparer<string>.Default.GetHashCode(Name)) *
-1521134295 +
EqualityComparer<string>.Default.GetHashCode(
Artikelstatus)) * -1521134295 +
EqualityComparer<DateOnly>.Default.GetHashCode(
ObjektErzeugungsZeitpunkt);
��}
��public override bool Equals(object obj)
��{
������return obj is Autor && Equals((Autor)obj);
��}
��public bool Equals(Autor other)
��{
����return EqualityComparer<int>.Default.Equals(ID,
other.ID) &&
EqualityComparer<string>.Default.Equals(Name,
other.Name) &&
EqualityComparer<string>.Default.Equals(Artikelstatus,
other.Artikelstatus) &&
EqualityComparer<DateOnly>.Default.Equals(
ObjektErzeugungsZeitpunkt,
other.ObjektErzeugungsZeitpunkt);
��}
��public void Deconstruct(out int ID, out string Name,
out string Artikelstatus)
��{
����ID = this.ID;
����Name = this.Name;
����Artikelstatus = this.Artikelstatus;
��}
}
(rme)