Journal
Sections
Réglages de lecture
Aucune voix pour cette langue dans ce navigateur.
Plus de voix
Code et termes techniques en anglais
Désactivé : la voix de la page lit tout, sans pause entre deux voix.
Aucune voix pour cette langue dans ce navigateur.
Plus de voix
D’autres voix : Microsoft Edge propose des voix naturelles en ligne, et Windows (Paramètres › Heure et langue › Voix), macOS et Android en installent d’autres.
Progression
Section intitulée « Progression »- Code du cours : applications basées sur des fichiers, extraits refusés et solutions des exercices, comparés à leur sortie attendue par
check.sh - CI sous Linux, Windows et macOS
- Leçon 1 : installer .NET et exécuter ton premier programme
- Leçon 2 : variables, types et saisie
- Leçon 3 : conditions et boucles
- Leçon 4 : méthodes, tableaux et listes
- Leçon 5 : classes et objets
- Leçon 6 : records, structs et enums
- Leçon 7 : interfaces et héritage
- Leçon 8 : exceptions et sécurité face à null
- Leçon 9 : collections et LINQ
- Leçon 10 : fichiers et texte
- Leçon 11 : tests unitaires
- Leçon 12 : un petit projet
| Attendu | Ce qui se passe | Où | Mesure | Statut |
|---|---|---|---|---|
Afficher un modèle d’accord de GA montre son Name, comme le veut le ToString() => Name du record de base |
Les records dérivés TonalModal et Analytical synthétisent chacun leur propre ToString, qui énumère toutes les propriétés : TonalModal { Name = Major 7th, PitchClassSet = 0 4 7 E, … }. Un record dérivé ne garde le ToString de la base que s’il est sealed (records, mise en forme intégrée) |
ChordTemplate.cs:84 ; un appelant, ContextualChordsController.cs:301, passe template.ToString() à un service qui le journalise (FretboardServices.cs:536) |
Une sonde console qui référence GA.Domain.Core au commit 5c3a52a, SDK 10.0.112 : le dump pour ToString() et $"{template}" sur les deux records ; une réplique avec sealed a affiché maj7 (entrée) |
Reproduit ; correctif proposé dans la PR GA n° 816, pas encore fusionnée (2026-10-04) ; toujours ouverte le 2026-10-06, le défaut inchangé sur main 40d33747 (2026-10-06) |
Les avertissements de nullabilité apparaissent dans le code de GA : GA.Domain.Core et GA.Core activent <Nullable>enable</Nullable> |
Directory.Build.props place 15 avertissements de nullabilité (CS8600, CS8602, CS8618, CS8625…) dans NoWarn « to achieve a clean baseline », et Directory.Build.targets les répète. La base est propre sans eux : les listes ne cachent que les nouvelles erreurs |
Directory.Build.props:21, Directory.Build.targets:7 | Un fichier contenant sept erreurs de nullabilité, ajouté à GA.Domain.Core au commit 5c3a52a : 0 avertissement avec la configuration de GA, 7 sans les deux listes ; sans ce fichier, 0 dans GA.Domain.Core et GA.Core (entrée, ga-probes) |
Reproduit ; non signalé à GA |
Les services de connaissances musicales de GA chargent ChordProgressions.yaml, GuitarTechniques.yaml et SpecializedTunings.yaml |
Aucun des trois ne se désérialise : une chaîne là où la classe a une List<string>, des chaînes là où elle attend des objets, une ligne qui n’est pas du YAML valide. Chaque chargeur attrape l’exception, affiche Error loading … et continue avec un seul élément par défaut |
ChordProgressions.yaml:93 face à ChordProgressionsConfigLoader.cs:16 ; GuitarTechniques.yaml:23 face à GuitarTechniquesConfigLoader.cs:20 ; SpecializedTunings.yaml:95 ; le catch de ChordProgressionsConfigLoader.cs:137, et le même dans les deux autres chargeurs |
artists.cs au commit 5c3a52a, SDK 10.0.112 : 17 accords emblématiques, puis 1 élément pour chacun des trois fichiers, et 16 artistes distincts (entrée). Les trois lignes sont inchangées sur le main de GA, ae196bf |
Reproduit ; signalé dans l’issue GA n° 797 le 2026-10-03 ; correctif proposé dans la PR GA n° 808, pas encore fusionnée (2026-10-04) |
GetArtistBreakdown renvoie les 20 artistes qui ont le plus d’entrées, du plus au moins, comme le dit son commentaire // Top 20 artists |
Take(20) coupe la liste alphabétique avant le tri par nombre d’entrées, et le résultat trié va dans un Dictionary, dont la documentation laisse l’ordre indéfini |
MusicalKnowledgeService.cs:226 et :235 ; GetAllArtists trie par nom en :125 |
La même sonde : avec 16 artistes, aucun n’est écarté, et le dictionnaire sort par nombre d’entrées, les égalités par ordre alphabétique. La coupe n’agit qu’au-delà de 20 artistes, une fois la ligne précédente corrigée | Latent, lu dans le code ; correctif proposé dans la PR GA n° 811, pas encore fusionnée (2026-10-04) |
PitchClassSet.ScaleVideoUrl donne l’URL de la vidéo d’une gamme listée dans scale_video_urls.json, qui en contient 1 490 |
Le fichier n’est ni intégré à la bibliothèque ni copié à côté d’elle : GA.Domain.Core.csproj n’a aucune règle pour lui. Le nom de ressource GA.Domain.Core.Scales.Data.scale_video_urls.json et le chemin de repli Scales/Data/ manquent tous deux son dossier, Theory/Tonal/Scales/Data/, et LoadVideoUrls renvoie un dictionnaire vide sans message |
ScaleVideoUrlById.cs:30, :36-38; PitchClassSet.cs:350, ScaleMetadataRegistry.cs:36 | files.cs au commit 5c3a52a, SDK 10.0.112 : 0 ressource dans GA.Domain.Core, pas de fichier de repli, 0 gamme avec une URL (entrée). Le nom de ressource et le chemin de repli sont inchangés sur le main de GA le 2026-10-03 |
Reproduit ; correctif proposé dans la PR GA n° 817, pas encore fusionnée (2026-10-04) ; toujours ouverte le 2026-10-06, le défaut inchangé sur main 40d33747 (2026-10-06) |
IconicChordsConfigLoader.ReloadConfiguration() relit IconicChords.yaml après une modification |
Il affecte le champ static readonly _configuration avec FieldInfo.SetValue, qui lève FieldAccessException depuis .NET Core 3.0 (changement cassant) |
IconicChordsConfigLoader.cs:107-111, :12 | files.cs : FieldAccessException: Cannot set initonly static field '_configuration' after type 'GA.Domain.Services.IconicChordsConfigLoader' is initialized. (entrée). Inchangé sur le main de GA le 2026-10-03 |
Reproduit ; correctif proposé dans la PR GA n° 811, pas encore fusionnée (2026-10-04) |
Un IconicChords.yaml manquant est signalé |
FindYamlFile essaie quatre chemins, dont deux relatifs au dossier courant. Quand aucun n’existe, un catch vide avale son FileNotFoundException, et le chargeur renvoie un seul accord par défaut, sans message |
IconicChordsConfigLoader.cs:94-104, :25-28 | files.cs, après suppression des fichiers YAML à côté de lui : 1 accord, « C Major Triad », lancé depuis ga-probes ; 17 depuis la racine du code de GA, par <dossier courant>/Common/GA.Business.Config ; rien d’affiché (entrée) |
Reproduit ; un choix de conception, non signalé à GA |
GaCLI lit le appsettings.yaml que sa compilation copie à côté du programme |
SetBasePath(Directory.GetCurrentDirectory()) le lit dans le dossier courant, comme un fichier facultatif : lancé depuis un autre dossier, GaCLI tournerait sans ses réglages, en silence |
Program.cs:17-19, GaCLI.csproj:59-61 | Compilé à 5c3a52a et lancé depuis un autre dossier : il affiche sa liste de commandes. Les deux sections du fichier, EmbeddingService et LmStudio, ne sont lues qu’à un endroit, sync-mongodb, dans des réglages qu’aucun service ne résout (entrée) |
Vérifié : le fichier ne change rien à ce commit ; non signalé à GA |
| Chaque ligne du CSV de naturalité de GA a les 6 valeurs de son en-tête | :F2 et {deltaStretch} utilisent la culture de la machine : avec fr-FR, 2.50 s’écrit 2,50, et une ligne reçoit 8 valeurs ; le lecteur coupe aux , |
NaturalnessTrainingDataGenerator.cs:160, :21; TrainNaturalnessModelCommand.cs:51-54 | l10_culture.cs avec la chaîne de format de GA : 6 valeurs avec en-CA, 8 avec fr-FR. Le générateur de GA lui-même n’a pas tourné : il lui faut un corpus de tablatures (entrée) |
Reproduit avec la chaîne de format ; correctif proposé dans la PR GA n° 811, pas encore fusionnée (2026-10-04) |
| La commande de GA affiche le nombre de lignes de données qu’elle a écrites | csvContent.Split('\n').Length - 1 retire l’élément vide après le dernier saut de ligne mais compte l’en-tête : une ligne de trop |
GenerateNaturalnessDataCommand.cs:38 | L’arithmétique de Split('\n'), mesurée par l10_line_endings.cs : 3 lignes donnent 4 éléments. La commande de GA n’a pas tourné |
Latent, lu dans le code ; correctif proposé dans la PR GA n° 811, pas encore fusionnée (2026-10-04) |
| Un test des services de connaissances musicales de GA échoue quand leurs fichiers YAML ne se chargent pas | Trois des huit tests sont ignorés avec [Ignore("Configuration files not loaded in test environment")]. Des cinq autres, trois vérifient seulement qu’un nombre est supérieur à zéro ou qu’une liste n’est pas vide, ce que satisfait le seul élément par défaut de chaque chargeur en échec |
MusicalKnowledgeServiceTests.cs:108-110, :141-143, :207-209; :16, :31-33, :179-183 | Sonde knowledge-tests, fichier de test de GA compilé sans changement, SDK 10.0.112 : 5 réussis, 3 ignorés, 0 échec, alors que trois des quatre fichiers YAML ne se chargent pas. La recherche de « jazz » a réussi avec 1 résultat, la progression d’accords par défaut (entrée). Inchangé sur le main de GA, 0843879 |
Reproduit ; lié à l’issue GA n° 797 ; correctif proposé dans la PR GA n° 808, pas encore fusionnée (2026-10-04) |
Le [SetUpFixture] TestEnvironment de GA s’exécute avant les tests de configuration : il définit GA_TEST_MODE=1 et place le dossier courant à la racine du dépôt |
Il est seul dans le namespace GA.Business.Core.Tests.TestBootstrap, et NUnit n’exécute un setup fixture que pour les tests de son namespace et des namespaces qu’il contient (NUnit) : il ne s’exécute jamais |
TestEnvironment.cs:1, :7-14 | Sonde knowledge-tests : un test dans GA.Business.Core.Tests.Configuration a affiché GA_TEST_MODE: (not set) et Current directory is the test's bin folder: True (entrée). Sur main, 0843879, le namespace ne contient toujours que ce fichier |
Reproduit ; correctif proposé dans la PR GA n° 816, pas encore fusionnée (2026-10-04) ; toujours ouverte le 2026-10-06, le défaut inchangé sur main 40d33747 (2026-10-06) |
| Les fichiers de test de GA.Business.Core.Tests sont compilés et exécutés | Le fichier projet retire 35 fichiers de la compilation, « Exclude test files with missing service implementations » : 5 des noms ne correspondent à aucun fichier, et les 30 autres contiennent 333 lignes qui commencent par [Test] ou [TestCase] |
GA.Business.Core.Tests.csproj:39-75 | git ls-tree et un décompte au commit 5c3a52a ; le projet a 136 fichiers .cs. Les 35 entrées sont inchangées sur main, 0843879 |
Compté dans le code ; non signalé à GA |
| La CI de GA exécute les tests de chaque projet de test | Ses jobs compilent et testent AllProjects.slnx, qui liste 75 des 111 fichiers de projet. Six projets de test sont en dehors et aucun workflow ne les nomme ; leurs fichiers comptent 102 lignes avec un attribut de test. L’un d’eux, GA.Business.Core.Graphiti.Tests, ne compile pas : il utilise GA.Business.Graphiti et ne référence aucun projet |
AllProjects.slnx, ci.yml:43, :103, GA.Business.Core.Graphiti.Tests.csproj | lesson12_counts.py à 5c3a52a ; la compilation des tests Graphiti s’arrête sur 5 erreurs, CS0234 sur ses deux lignes using GA.Business.Graphiti... et CS0246 |
Compté et compilé ; correctif proposé dans la PR GA n° 812, pas encore fusionnée (2026-10-04) |
Les éléments PackageReference Update du Directory.Build.props de GA alignent les versions des packages, sous « Centralized package version alignment and vulnerability remediation » |
Directory.Build.props est importé avant les éléments propres du projet, donc Update ne trouve rien à mettre à jour. 23 déclarations des six packages concernés gardent une autre version, dont 13 dans des projets de la solution |
Directory.Build.props:32-58 | Restauration de GA.Business.Core.Graphiti.Tests : Microsoft.Extensions.Http 9.0.10, comme le demande son fichier de projet. Avec la même ligne Update dans Directory.Build.targets : 10.0.0 |
Reproduit, avec un témoin ; correctif proposé dans la PR GA n° 812, pas encore fusionnée (2026-10-04) |
| Le job d’analyse de sécurité de GA signale les packages vulnérables | Directory.Build.props et Directory.Build.targets désactivent NU1902, NU1903 et NU1904 pour tous les projets. L’étape d’analyse a continue-on-error: true, et dotnet list package --vulnerable se termine avec le code 0 quand il liste un package vulnérable : le job ne peut pas échouer |
Directory.Build.props:16-17, Directory.Build.targets:5-11, ci.yml:398-401 | Code de sortie 0 avec un package vulnérable, mesuré sur un projet d’essai (tableau des expériences) ; l’analyse de GA n’a pas été lancée | Lu dans le code ; correctif proposé dans la PR GA n° 812, pas encore fusionnée (2026-10-04) |
| Le workflow Quality Check de GA lance un benchmark de qualité de GaCLI | benchmark-quality lève NotImplementedException, comme 12 des 28 commandes de GaCLI, y compris analyze-chord, le premier exemple de son aide. L’étape a continue-on-error: true |
quality_check.yml:26-29, Program.cs:179-182 | Compilation locale à 5c3a52a : NotImplementedException non gérée. Run 37167745677 de GA, sur un commit plus récent dont le workflow et Program.cs sont les mêmes fichiers : code de sortie 134, run conclu en succès |
Reproduit ; non signalé à GA |
| Une commande de GaCLI qui échoue le dit à son appelant | sync-mongodb attrape son exception, affiche Error during sync: Unable to resolve service for type 'GA.Data.MongoDB.Services.MusicalObjectsService' while attempting to activate 'GaCLI.Commands.Runner'. et se termine avec le code 0 : Runner a besoin d’un service que la commande n’enregistre pas |
Program.cs:356, :364-368 | Lancé depuis bin/Debug/net10.0 et depuis un autre dossier : le même message, code de sortie 0 |
Reproduit ; correctif proposé dans la PR GA n° 811, pas encore fusionnée (2026-10-04) |
Expériences
Section intitulée « Expériences »| Question | Hypothèse, écrite avant de mesurer | Résultat | Verdict | Entrée et code |
|---|---|---|---|---|
Combien d’avertissements de nullabilité le NoWarn de GA cache-t-il dans GA.Domain.Core ? |
Plus de 100 | 0 dans GA.Domain.Core et GA.Core sans les deux listes ; un fichier de test contenant sept erreurs reçoit 7 avertissements sans les listes, 0 avec | Réfutée | entrée, ZzNullableCanary.cs |
Que fait le Fret de GA avec 50 ? |
new Fret(50), Fret.FromValue(50) et Fret f = 50; lèvent une ArgumentOutOfRangeException ; Fret.TryCreate(50) renvoie l’échec Fret number must be between -1 (muted) and 36, got 50 |
Les trois lèvent l’exception, pour 50 et pour -2 ; le message de TryCreate correspond mot pour mot |
Confirmée | entrée, probe.cs, results.txt |
new PositionLocation(5, 3), avec la corde et la frette inversées sous forme de simples nombres, compile-t-il sans rien dire ? |
Les deux ordres compilent sans avertissement ; l’appel inversé construit la corde 5, frette 3 | 0 avertissement sur les lignes de la sonde ; elle affiche 5,3 |
Confirmée | entrée, probe.cs |
Dans quel ordre un foreach lit-il un dictionnaire après un Remove et un Add ? |
Clés C, D, E, G, A, puis Remove("D") et Add("F#") : F# prend la place de D, C F# E G A, pas la dernière place |
C F# E G A |
Confirmée | entrée, l09_dictionary_order.cs |
Modifier un dictionnaire dans son propre foreach lève-t-il une exception, comme pour une liste ? |
Remove ne lève rien sous .NET 10 ; ajouter une clé lève une exception ; List<T>.Remove lève une InvalidOperationException |
Remove laisse C E sans exception ; ajouter B, et le Remove de la liste, lèvent tous deux Collection was modified; enumeration operation may not execute. |
Confirmée | entrée, l09_modify_dictionary.cs, l09_modify_while_looping.cs |
Quels artistes le GetArtistBreakdown de GA écarte-t-il avec Take(20) ? |
Plus de 20 artistes distincts : les 20 premiers de l’alphabet sont gardés, et au moins un artiste écarté a plus d’entrées que le plus petit nombre gardé ; le dictionnaire sort par nombre d’entrées décroissant | 16 artistes, aucun écarté, parce que trois des quatre fichiers YAML ne se chargent pas (tableau QA). Le dictionnaire sort bien par nombre d’entrées, les égalités par ordre alphabétique | Réfutée | entrée, artists.cs, artists-results.txt |
Sur un fichier de 3 lignes qui finit par un saut de ligne, que renvoient ReadAllText(path).Split('\n') et ReadAllLines, en LF et en CRLF ? |
Split donne 4 éléments, le dernier vide, et en CRLF les trois premiers finissent par \r ; ReadAllLines donne 3 lignes sans \r dans les deux cas |
Longueurs LF 2 2 2 0 et 2 2 2, CRLF 3 3 3 0 et 2 2 2 ; en CRLF, split[0] == "E2" vaut False |
Confirmée | entrée, l10_line_endings.cs |
Combien d’octets écrivent WriteAllText(path, "Ré") et WriteAllText(path, "Ré", Encoding.UTF8) ? |
3 sans encodage, 6 avec Encoding.UTF8, en commençant par EF BB BF ; ReadAllText renvoie Ré dans les deux cas |
52C3A9, puis EFBBBF52C3A9 ; Ré, 2 caractères |
Confirmée | entrée, l10_bom.cs |
File.Exists("data/ga-projects.csv") dépend-il du dossier d’où part dotnet run ? |
True depuis code/csharp-beginner, False depuis la racine du dépôt ; un chemin construit à partir de EntryPointFileDirectoryPath existe depuis les deux |
Comme prévu, et False aussi depuis examples ; check.sh exécute maintenant les deux cas sur trois OS. EntryPointFileDirectoryPath lui-même était connu avant l’hypothèse |
Confirmée | entrée, l10_where.cs |
Fichiers YAML supprimés à côté de la sonde, combien d’accords emblématiques GA charge-t-il, lancé depuis la racine de GA et depuis ga-probes ? |
17 depuis la racine de GA, par le troisième chemin ; 1 accord par défaut depuis ga-probes, sans exception ni message |
17, « Hendrix Chord » en premier, et 1, « C Major Triad » ; rien d’affiché | Confirmée | entrée, files.cs, files-without-yaml.txt, files-from-ga-root.txt |
Que fait IconicChordsConfigLoader.ReloadConfiguration() de GA sous .NET 10 ? |
Il lève FieldAccessException : SetValue sur un champ static readonly est refusé depuis .NET Core 3.0 |
FieldAccessException: Cannot set initonly static field '_configuration' … |
Confirmée | entrée, files.cs, files-results.txt |
Combien de valeurs séparées par des virgules a une ligne du CSV de naturalité de GA avec en-CA et avec fr-FR ? |
6 avec en-CA, 1,2.50,2.50,2,1,4 ; 8 avec fr-FR, 1,2,50,2,50,2,1,4. Connu avant l’hypothèse : $"{2.5}" donne 2,5 avec fr-FR |
Exactement ces deux lignes | Confirmée | entrée, l10_culture.cs |
Quelle taille a un fichier après StreamWriter.Write("E2 A2 D3"), avant et après Dispose ? |
0 octet avant, 8 après | 0, puis 8 | Confirmée | entrée, l10_dispose.cs |
ScaleVideoUrlById de GA trouve-t-il ses données ? |
Pas de ressource nommée …scale_video_urls.json dans GA.Domain.Core, pas de fichier de repli à côté de la sonde, un résultat vide, pas d’exception. La lecture d’un sous-agent l’a suggéré avant que je lise le code |
0 ressource en tout, pas de fichier de repli, 0 gamme avec une URL | Confirmée | entrée, files.cs |
Que crée dotnet new xunit avec le SDK 10.0.112, et qu’affiche dotnet test ? |
xUnit v2, package xunit 2.9.x, avec xunit.runner.visualstudio, Microsoft.NET.Test.Sdk et coverlet.collector ; exécuté par VSTest, avec une ligne Passed! à la fin |
xunit 2.9.3, xunit.runner.visualstudio 3.1.4, Microsoft.NET.Test.Sdk 17.14.1, coverlet.collector 6.0.4 ; VSTest 18.0.2 ; Passed! - Failed: 0, Passed: 1, … |
Confirmée | entrée, Fretboard.Tests.csproj |
Une [Theory] avec quatre lignes [InlineData] compte-t-elle pour 4 tests ou pour 1 ? |
4 | 15 tests dans le projet : la théorie comptée une seule fois en aurait donné 12 | Confirmée | entrée, GuitarTests.cs |
Que font Assert.Equal(0.3, 0.1 + 0.2) et Assert.Equal(0.3, 0.1 + 0.2, 10) ? |
Le premier échoue et affiche la valeur obtenue 0.30000000000000004 ; le second réussit |
Comme prévu. Non prévu : la valeur attendue est affichée 0.29999999999999999 |
Confirmée | entrée, PitfallTests.cs |
Quand la méthode lève ArgumentOutOfRangeException, que font Assert.Throws<ArgumentException> et Assert.ThrowsAny<ArgumentException> ? |
Throws échoue, il veut le type exact ; ThrowsAny réussit |
Assert.Throws() Failure: Exception type was not an exact match ; ThrowsAny réussit |
Confirmée | entrée, PitfallTests.cs, GuitarTests.cs |
| xUnit crée-t-il une nouvelle instance de la classe de test pour chaque test ? | Oui : un champ incrémenté par chacun de deux tests vaut 1 dans les deux | Les deux tests réussissent | Confirmée | entrée, InstanceTests.cs |
Exécutés sans changement contre les services de GA au commit 5c3a52a, que donnent les MusicalKnowledgeServiceTests de GA ? |
0 échec, 3 ignorés, 5 réussis, dont le test des accordages spéciaux, car le seul accordage par défaut rend sa liste non vide. Écrite après lecture du fichier de test, avant de l’exécuter | 5 réussis, 3 ignorés, 0 échec ; 1 accordage spécial, « Overall Valid: True » | Confirmée | entrée, knowledge-tests, knowledge-results.txt |
Le [SetUpFixture] TestEnvironment de GA s’exécute-t-il avant les tests de GA.Business.Core.Tests.Configuration ? |
Non : il est seul dans son namespace. Un test de sonde à côté de ceux de GA voit GA_TEST_MODE non défini et son dossier bin comme dossier courant. Écrite après lecture du bootstrap, avant l’exécution |
GA_TEST_MODE: (not set), Current directory is the test's bin folder: True |
Confirmée | entrée, knowledge-tests, knowledge-results.txt |
Que crée dotnet new sln avec le SDK 10.0.112 ? |
Un fichier .slnx, pas un .sln |
Fretboard.slnx : <Solution> et </Solution>, aucun projet |
Confirmée | entrée, l12-project |
Dans le dossier d’une solution avec une bibliothèque, une application console et un projet de test, que compilent et exécutent dotnet build et dotnet test ? |
dotnet build compile les trois projets ; dotnet test exécute seulement les tests du projet de test |
dotnet build : Fretboard, Fretboard.App, Fretboard.Tests. dotnet test : un assembly de test, 6 réussis. Non prévu : après dotnet clean, dotnet test laisse Fretboard.App non compilé |
Confirmée | entrée, l12-project |
Avec une erreur de compilation dans l’application console, que font dotnet test et dotnet build dans le dossier de la solution ? Écrite après avoir vu l’application non compilée, avant cette exécution |
dotnet test réussit et se termine avec le code 0 ; dotnet build échoue |
dotnet test : réussi, code de sortie 0. dotnet build : compilation échouée, code de sortie 1 |
Confirmée | entrée |
Qu’écrit dotnet add package CsvHelper, et CsvHelper lit-il une valeur entre guillemets qui contient une virgule comme un seul champ ? |
La dernière version stable ; oui, là où Split(',') donne un champ de trop |
Version="33.1.0" le 3 octobre 2026 ; Split : 4 champs, CsvHelper : 3 |
Confirmée | entrée, l12_csvhelper.cs |
#:package fonctionne-t-il dans une application basée sur un fichier, avec et sans version ? |
#:package CsvHelper@33.1.0 restaure et s’exécute ; sans @version la restauration le refuse |
3 champs ; sans la version, error NU1015: The following PackageReference item(s) do not have a version specified: CsvHelper, code de sortie 1 |
Confirmée | entrée, l12_package_no_version.cs |
GetRecords<Project>() de CsvHelper peut-il remplir un record positionnel qui a aussi une propriété calculée ? |
Oui, par son constructeur, d’après les noms de l’en-tête, en ignorant SourceFiles |
12 records et 632 fichiers source ; leur liste est égale à une liste construite à la main | Confirmée | entrée, ProjectFileTests.cs |
Que fait dotnet pack sans option d’une bibliothèque qui référence CsvHelper ? |
Une compilation Release, bin/Release/Fretboard.1.0.0.nupkg, un zip avec lib/net10.0/Fretboard.dll et un .nuspec qui liste CsvHelper « >= 33.1.0 » |
Comme prévu ; le .nuspec écrit version="33.1.0", la notation de NuGet pour 33.1.0 ou plus, avec exclude="Build,Analyzers". Non prévu : le message sur le readme, le commit de HEAD dans le .nuspec, et un second dotnet pack sans changement qui n’affiche aucune des deux lignes |
Confirmée | entrée, l12_ex_package.cs |
Un package qui a un avis de sécurité connu provoque-t-il un avertissement, et dotnet list package --vulnerable échoue-t-il ? |
Newtonsoft.Json 12.0.1 donne NU1903 à la restauration ; la commande le liste et se termine avec le code 0 | NU1903 avec GHSA-5crp-9r3c-p9vr, affiché deux fois par une application basée sur un fichier ; dotnet list package --vulnerable et dotnet package list --vulnerable affichent le tableau et se terminent avec le code 0 |
Confirmée | entrée, l12_audit.cs |
Combien de temps prennent deux Task.Delay(500), attendus l’un après l’autre puis avec Task.WhenAll ? |
Au moins 1000 ms ; moins de 900 ms | Cinq exécutions : de 1014 à 1023 ms, puis de 508 à 514 ms | Confirmée | entrée, l12_async.cs |
Que devient un appel async sans await dans un programme à instructions de niveau supérieur ? |
Avertissement CS4014, et la ligne écrite après son délai n’apparaît jamais | CS4014 en (2,1) ; Before, After, code de sortie 0 |
Confirmée | entrée, l12_forgotten_await.cs |
Que dit le compilateur d’un await dans un constructeur, et d’un constructeur async ? |
CS4033 ; CS0106, modificateur non valide | CS4033, comme prévu. public async VoicingIndex() donne CS0246 pour un type async et CS0542, un membre nommé comme son type : l’analyseur lit une méthode |
Partiellement réfutée | entrée, l12_constructor_await.cs |
AllProjects.slnx de GA liste-t-il tous les fichiers de projet du dépôt ? |
Non : au moins 5 .csproj ou .fsproj manquent |
36 des 111 manquent ; aucun n’est listé sans exister | Confirmée | entrée, lesson12_counts.py, lesson12-results.txt |
| Les projets de test de GA hors de la solution tournent-ils dans la CI, et des projets hors de la solution sont-ils compilés quand même ? Écrite après le comptage précédent | Au moins un projet de test n’est nommé par aucun workflow ; au moins un projet hors de la solution est référencé par un projet listé | Six projets de test, 102 lignes avec un attribut de test, nommés par aucun workflow ; 7 projets hors de la solution référencés, GA.Business.Core par 4 |
Confirmée | entrée, lesson12_counts.py, lesson12-results.txt |
GA.Business.Core.Graphiti.Tests compile-t-il ? Écrite après avoir lu son fichier de projet et son test |
Non : il utilise GA.Business.Graphiti sans ProjectReference, donc CS0246 |
5 erreurs : CS0234 aux lignes 7 et 8, puis CS0246 | Confirmée | entrée, ga-probes |
| Un package est-il déclaré avec plusieurs versions dans les fichiers de projet de GA ? | Oui, au moins un | 35 packages ; Microsoft.Extensions.Hosting et MongoDB.Driver avec cinq versions chacun |
Confirmée | entrée, lesson12_counts.py, lesson12-results.txt |
Les éléments PackageReference Update du Directory.Build.props de GA changent-ils une version ? Écrite après avoir lu le fichier |
Non : Microsoft.Extensions.Http reste à la 9.0.10 du fichier de projet des tests Graphiti |
9.0.10 ; avec la même ligne dans Directory.Build.targets, 10.0.0, alors que Microsoft.Extensions.Options, mis à jour dans le seul fichier props, reste à 9.0.10 |
Confirmée | entrée, ga-probes |
| Le code de GA hors tests bloque-t-il sur des tâches à au moins 20 endroits ? | Oui | 27 correspondances de .Result, .Wait() et GetAwaiter().GetResult() : 4 sont des SemaphoreSlim.Wait(), 7 lisent des tâches après await Task.WhenAll, 5 sont dans des fichiers retirés de la compilation ; il en reste 11, dont 3 dans des constructeurs |
Réfutée | entrée, lesson12_counts.py, lesson12-results.txt |
GA a-t-il une méthode async void qui n’est pas un gestionnaire d’événement ? |
Oui, au moins une | Aucune | Réfutée | entrée, lesson12_counts.py |
GaCLI tourne-t-il depuis un autre dossier sans appsettings.yaml, et sync-mongodb démarre-t-il ? Écrite après avoir lu Program.cs |
Il affiche son aide ; sync-mongodb s’arrête sur un MusicalObjectsService manquant, depuis les deux dossiers |
Aide affichée ; Error during sync: Unable to resolve service for type 'GA.Data.MongoDB.Services.MusicalObjectsService'... depuis les deux dossiers, code de sortie 0 |
Confirmée | entrée, ga-probes |
2026-09-14 — Le SDK et les applications basées sur des fichiers
Section intitulée « 2026-09-14 — Le SDK et les applications basées sur des fichiers »- Ma machine a deux SDK : 10.0.112 et 11.0.100-preview.3.26207.106. Sans
global.json,dotnetchoisit la préversion. Le dossier du cours fixe10.0.100avecrollForward: latestFeature, ce qui sélectionne ici 10.0.112. - Le même jour, WinGet propose
Microsoft.DotNet.SDK.10en version 10.0.401 : une bande de fonctionnalités plus récente que la mienne. La page des applications basées sur des fichiers indique que#:includeest disponible à partir du SDK 10.0.300 ; la leçon 1 dit donc qu’une application basée sur un fichier tient en un seul fichier par défaut, et que#:includeen ajoute d’autres à partir de ce SDK. Je n’ai pas essayé#:include: mon SDK est plus ancien. - Les exemples sont des applications basées sur des fichiers plutôt qu’un projet par leçon : un débutant tape un fichier et l’exécute, sans rien configurer. Un simple
dotnet run app.csa pris 0,9 s la première fois et 0,2 s la suivante. - Les autres fichiers
.csdu même dossier ne sont pas compilés avec l’application :hello.csa fonctionné à côté d’un fichier plein d’erreurs. - Les avertissements ne s’affichent que quand le SDK compile. Un second
dotnet rund’un fichier inchangé n’affiche aucun avertissement, etdotnet run --no-cachen’y change rien : il saute la vérification « à jour » de l’application basée sur un fichier, mais MSBuild trouve toujours la sortie compilée à jour et n’appelle pas le compilateur. Undotnet clean app.csavant chaque exécution fait revenir les avertissements ;check.shle fait, et la leçon 3 le dit au lecteur. - Les erreurs du compilateur vont sur la sortie standard, avec le chemin complet du fichier ;
The build failed. Fix the build errors and run again.va sur la sortie d’erreur.check.shfusionne les deux et ne garde que le nom du fichier, pour que les fichiers attendus soient les mêmes sur toutes les machines. - Les erreurs de syntaxe cachent les autres : dans le programme cassé de l’exercice 2 de la leçon 1, la faute de frappe
Writeline(CS0117) n’est signalée qu’une fois le;et le guillemet manquants corrigés. L’exercice repose là-dessus. - Entrée standard : quand l’entrée vient d’un fichier, le texte tapé n’apparaît pas dans la sortie, donc les fichiers attendus contiennent les questions directement suivies des réponses. Les leçons montrent le terminal tel qu’une personne le voit, avec les lignes tapées, et le disent.
- Culture : la culture de mon Windows est
en-CA. Aveces-ES,double.TryParse("1.5")renvoietrueet 15, car le point sépare les milliers en espagnol ; avecfr-FR, il renvoiefalse. L’exemple fixe chaque culture explicitement, donc la sortie est la même sur tous les OS. Les autres exemples n’utilisent que des formats qui s’affichent de la même façon enen-CA, enen-USet dans la culture invariante du runner Linux.
2026-09-14 — CI
Section intitulée « 2026-09-14 — CI »- Commit
b19a296, exécution 34914488934 : verte sur les trois OS.actions/setup-dotnet, avec leglobal.jsondu cours, a installé le SDK 10.0.401 sur les trois runners, alors que les sorties ont été capturées avec 10.0.112 : tous les messages du compilateur sont identiques. Les jobs ont pris 54 s sous Linux, 1 min 36 s sous macOS et 2 min 18 s sous Windows, avec undotnet cleanet une compilation pour chacune des 58 applications basées sur des fichiers. Math.Pow(2, 7 / 12.0)affiché avec tous ses chiffres,164.81377845643496, est le même sur les trois OS.- La ligne shebang
#!/usr/bin/env -S dotnet --fonctionne sur les runners Linux et macOS aprèschmod +x, etdotnet runl’ignore sous Windows. - Les codes de sortie d’une exception non gérée diffèrent, donc
check.shles affiche et ne compare queexit crash:- Linux et macOS : 134 (le processus s’interrompt,
SIGABRT) pour les trois exemples qui plantent ; - Windows, vu depuis Git Bash : 127 pour
IndexOutOfRangeExceptionetSwitchExpressionException, et 139 avec un message « Segmentation fault » pourNullReferenceException; - Windows, vu depuis PowerShell :
0xE0434352(-532462766), le code d’une exception .NET, pourIndexOutOfRangeException, mais0xC0000005(-1073741819), une violation d’accès, pourNullReferenceException.
- Linux et macOS : 134 (le processus s’interrompt,
2026-09-14 — Dogfooding
Section intitulée « 2026-09-14 — Dogfooding »- Les exemples utilisent Guitar Alchemist comme petites données : l’accordage standard de
Tuning.Defaultau commita826864, et douze noms de projets decode/ladybugdb/data/ga/projects.csv, extraits au commita26a7893. Rien dans ces leçons n’a révélé de problème dans GA.
2026-09-29 — Classes et objets
Section intitulée « 2026-09-29 — Classes et objets »- La leçon 5 présente la construction, l’identité des instances, les champs privés, les propriétés publiques, les méthodes et un compteur
staticpartagé, puis propose de créer une classePracticeSession. Les pages anglaise, française et espagnole contiennent les mêmes extraits C# testés et les mêmes sorties du compilateur. - Sous Windows, avec le SDK 10.0.112,
C:/Program Files/Git/bin/bash.exe check.sha réussi pour les exemples, les solutions et les extraits refusés du cours, y compris les nouveaux fichiersl05_*. Les deux nouveaux extraits refusés ont produit respectivement CS0122 et CS0200. Lebashpar défaut de la machine était celui de WSL et ne trouvait pas ledotnetWindows : ce premier échec venait de l’environnement de test, pas du code. - Ce résultat local ne remplace pas une nouvelle CI sur trois OS et ne prouve pas que la leçon est publiée. Les leçons 6 à 12 restent au stade de plan.
2026-09-30 — La leçon 5 dans la CI sur trois OS
Section intitulée « 2026-09-30 — La leçon 5 dans la CI sur trois OS »- Le run 36664604662 du workflow C# for beginners examples, sur le commit
669d42ade la PR #60, a réussi sousubuntu-latest,windows-latestetmacos-latest. Dans la sortie de chaque job,check.shafficheokpourl05_objects,l05_ex_practice,l05_get_only_propertyetl05_private_field: les sorties et les diagnostics CS0122 et CS0200 correspondent àexpected/sur les trois OS.
2026-10-01 — Records, structs et enums
Section intitulée « 2026-10-01 — Records, structs et enums »- La leçon 6 compare une structure et une classe (copie à l’affectation, copie en argument,
Equals), puis présente les records (==sur les données,ToString,with,readonly record struct) et les énumérations (numérotées à partir de 0, valeur par défaut, casts,Enum.IsDefined,Enum.Parse). Elle compte quatre exemples, trois exercices et cinq extraits refusés, dont les diagnostics sont CS0019, CS1612, CS8852 (trois fois dans deux fichiers) et CS0266. Un script a vérifié que les trois langues partagent les mêmes blocs de code, commentaires mis à part, et que chaque bloc correspond à son fichier danscode/csharp-beginneretexpected/. - Sous Windows, avec le SDK 10.0.112 et Git Bash,
check.shs’est terminé avec le code 0 et 75 lignesok, dont les 12 fichiersl06_*. Ce n’est pas encore une exécution de la CI sur trois OS. - Puis dans la CI : le run 36865237779 du workflow C# for beginners examples, sur le commit
114b5edde la PR #93, a réussi sousubuntu-latest,windows-latestetmacos-latest. Chaque job afficheokpour les 12 fichiersl06_*; les jobs comptent 76 lignesoksous Linux et macOS et 75 sous Windows, carcheck.shne lance l’exemple à shebang avec./que sous Linux et macOS. - Surprises, toutes reprises dans la leçon : CS8524 avertit pour une expression
switchqui a une branche par nom, et son exemple est(ChordQuality)5alors que le programme échoue sur 7 ; le littéral0se convertit en énumération sans cast, alors que2donne CS0266 ; uneList<T>de structures modifiables refuseshape[0].Fret = 5avec CS1612. - Un brouillon de l’exercice 3 disait que
shape[i].Fret += 2sur une liste dereadonly record structdonne le même CS1612. Une sonde compilée avant publication a donné CS8852 ; le texte a été corrigé, etcompile_fail/l06_readonly_position.csconserve désormais les deux lignes CS8852. Deux autres phrases reposent sur des sondes restées hors du code du cours : ranger une copie modifiée avecshape[0] = position;a affiché 5, etList<T>.Containssur une classe sans égalité propre a réponduFalse. - Dogfooding : au commit
5c3a52ade GA,ChordQualitycommence parOther, etPositionLocation,StretFretsont des typesreadonly record struct. Rien dans cette leçon n’a révélé de problème dans GA.
2026-10-01 — Interfaces et héritage
Section intitulée « 2026-10-01 — Interfaces et héritage »- La leçon 7 construit
GuitaretUkulelesur une classe de baseStringInstrument(base(...),virtual,override,base.Describe(),ToString), puis une classe abstraiteInstrumentavec une méthode abstraitePlay, puis une interfaceIHasRangequ’une classe et un record implémentent tous deux. Elle compte quatre exemples, dont un qui compile avec l’avertissement CS0114, trois exercices et cinq extraits refusés, dont les diagnostics sont CS0506, CS0509, CS0144, CS0534 et CS0535. Le script utilisé pour la leçon 6 a vérifié les 20 blocs de code des trois langues contrecode/csharp-beginneretexpected/. - Sous Windows, avec le SDK 10.0.112 et Git Bash,
check.shs’est terminé avec le code 0 et 87 lignesok, dont les 12 fichiersl07_*. Ce n’est pas encore une exécution de la CI sur trois OS. - Puis dans la CI : le run 36893689911 du workflow C# for beginners examples, sur le commit
b347f7dde la PR #95, a réussi sousubuntu-latest,windows-latestetmacos-latest. Chaque job afficheokpour les 12 fichiersl07_*; les jobs comptent 88 lignesoksous Linux et macOS et 87 sous Windows, pour la même raison qu’à la leçon 6. - Deux phrases du brouillon ne reposaient sur aucune exécution et ont changé avant publication. Que seule une variable de type
Ukuleletrouve une méthode qui masque est désormais une ligne deexamples/l07_hiding_warning.cs, qui affichea ukulele. « Les numéros MIDI sont ceux de la leçon 4, où do4 vaut 60 » était faux, puisque la leçon 4 ne donne aucun numéro MIDI ; la phrase dit maintenant que les numéros MIDI comptent des demi-tons, 12 par octave. - Dogfooding : au commit
5c3a52ade GA,ChordTemplateest un record abstrait dont les records dérivésTonalModaletAnalyticalredéfinissentName, et dont le propreToString() => Namen’est passealed. La page sur les records dit qu’unToStringsealedempêche le compilateur d’en synthétiser un dans les records dérivés (mise en forme intégrée pour l’affichage) ; celui-ci devait donc être masqué. Une sonde l’a confirmé : un projet console qui référence GA.Domain.Core et GA.Domain.Services au commit5c3a52a, compilé avec le SDK 10.0.112, a affichéTonalModal { Name = Major 7th, PitchClassSet = 0 4 7 E, … }pourToString()et pour$"{template}"sur unTonalModal, sur unAnalyticalet surChordTemplateFactory.CreateModalChords(...).First(), et la réflexion a désigné le record dérivé comme le type qui déclareToString. Une réplique de même forme avecpublic sealed override string ToString() => Namea affichémaj7. Un seul site d’appel en dépend : ContextualChordsController.cs:301 passetemplate.ToString()àGetVoicingsForChordAsync, qui le journalise (FretboardServices.cs:536) ; la réponse HTTP prend le nom de l’accord dans la route, pas dans cette chaîne. Le constat figure dans le tableau QA ; il n’a pas été signalé à GA.
2026-10-02 — Exceptions et sécurité face à null
Section intitulée « 2026-10-02 — Exceptions et sécurité face à null »- La leçon 8 attrape des exceptions avec
tryetcatch, avec un diagramme des classes d’exception ; exécutefinallyaprès unreturn, après uncatchet avant qu’une exception quitte la méthode ; lève uneArgumentOutOfRangeExceptionavecnameof; puis revient surnull: CS8600 et CS8618,required, l’opérateur!, etWarningsAsErrors=nullabledéfini avec#:property. Elle compte six exemples, quatre fichiers d’exercice (dont le point de départ de l’exercice 3, avec quatre avertissements) et cinq extraits refusés, dont les diagnostics sont CS0160, CS0165, CS0029, CS9035 et CS8602 en erreur. Le script utilisé pour les leçons 6 et 7 a vérifié les 28 blocs de code des trois langues contrecode/csharp-beginneretexpected/. - Sous Windows, avec le SDK 10.0.112 et Git Bash,
check.shs’est terminé avec le code 0 et 102 lignesok, dont les 15 fichiersl08_*. Ce n’est pas encore une exécution de la CI sur trois OS. - La première exécution de la CI de la PR #109 a échoué sous Linux seulement (run 36968274101) : le runner Linux a affiché les avertissements de
l08_null_warnings.csetl08_ex_null_start.csdans l’ordre des lignes, alors que Windows, en local comme dans la CI, et macOS affichaient CS8618 en premier. Les messages eux-mêmes étaient identiques.check.shplace désormais les messages du compilateur en premier, les erreurs avant les avertissements, chaque groupe trié par ligne et colonne, et la leçon montre cet ordre. Aucun fichier attendu des leçons 1 à 7 n’a changé : leurs messages venaient déjà dans cet ordre. - Puis, avec cette correction : le run 37009963497 du workflow C# for beginners examples, sur le commit
e2a95efde la PR #109, a réussi sousubuntu-latest,windows-latestetmacos-latest. Chaque job afficheokpour les 15 fichiersl08_*; les jobs comptent 103 lignesoksous Linux et macOS et 102 sous Windows, pour la même raison qu’à la leçon 6. - Surprises, toutes reprises dans la leçon :
throw "fret out of range";donne CS0029, une erreur de conversion, là où j’attendais CS0155 (The type caught or thrown must be derived from System.Exception) ;string capo = null;sur une variable locale donne CS8600, pas CS8625, alors que le fichier de test de GA ci-dessous a reçu CS8625 pour un argumentnull; dansl08_null_warnings.cs, CS8618 se trouve sur la déclaration de la propriété et la ligne qui plante n’a aucun avertissement ;tuner offs’affiche avant la valeur que renvoieTune. - Une phrase repose sur une sonde restée hors du code du cours : sans sa vérification,
NoteOfString(standard, 7)échoue avec uneIndexOutOfRangeException. - Dogfooding au commit
5c3a52ade GA, avec les hypothèses écrites avant de mesurer dans le tableau des expériences, et les sondes et leur mode d’emploi danscode/csharp-beginner/ga-probes:NoWarnliste quinze avertissements de nullabilité dans Directory.Build.props:21, et à nouveau dans Directory.Build.targets:7. J’attendais plus de 100 avertissements cachés dans GA.Domain.Core ; sans les deux listes, GA.Domain.Core et GA.Core n’en ont aucun.ZzNullableCanary.cs, sept erreurs de nullabilité ajoutées à GA.Domain.Core, a compilé sans avertissement avec les listes, et avec ses sept avertissements (CS8600 ×2, CS8602 ×3, CS8618, CS8625) sans elles. L’hypothèse est réfutée, et le tableau QA garde le constat : les listes ne cachent que les erreurs à venir.new Fret(50),Fret.FromValue(50)etFret f = 50;lèvent tous uneArgumentOutOfRangeException, pour 50 et pour -2, comme prévu, etFret.TryCreate(50)renvoieFailure(Fret number must be between -1 (muted) and 36, got 50). Le message de l’exception nomme une constante privée,GA.Domain.Core.Instruments.Primitives.Fret value (50) cannot be greater than _maxValue (36). (Parameter 'value'), parce que IRangeValueObject.cs le construit à partir des expressions de l’appelant, et sonActualValuereste vide.- La question ouverte du 2026-10-01 a sa réponse :
new PositionLocation(5, 3), avec la corde et la frette inversées sous forme de simples nombres, compile sans avertissement et construit la corde 5, frette 3. Une compilation avec tous les analyseurs (AnalysisLevel=latest-all) n’a demandé, sur ces lignes, que des types explicites à la place devar. Les conversions implicites depuisint(Str.cs:45, Fret.cs:72) laissent passer l’inversion.
2026-10-02 — Collections et LINQ
Section intitulée « 2026-10-02 — Collections et LINQ »- La leçon 9 couvre
Dictionary<TKey, TValue>: l’indexeur,Add,TryGetValue, le comptage avecGetValueOrDefault, et l’ordre d’unforeach. Elle couvreHashSet<T>, avec ses opérations d’ensemble sur des copies etSetEquals. Elle présente les lambdas, puis LINQ sur les projets de GA de la leçon 4, devenus des records :Count,Where,Select,OrderBy,ThenBy,First,FirstOrDefault,Any,All,TakeetToList. Elle finit par l’exécution différée, et par la modification d’une collection dans son propreforeach. Elle compte dix exemples, quatre exercices et quatre extraits refusés : CS1503, CS0021, CS0266, et CS0029 avec CS1662 sur la même colonne. Le vérificateur de blocs a mis en correspondance les 37 blocs de code de chaque langue aveccode/csharp-beginneretexpected/. - La leçon 4 annonçait que la leçon 5 remplacerait ses deux tableaux de projets par une seule liste ; la leçon 5 ne l’a pas fait. La leçon 9 le fait, et la leçon 4 renvoie désormais vers elle.
- Sous Windows, avec le SDK 10.0.112 et Git Bash,
check.shs’est terminé avec le code 0 et 120 lignesok, dont les 18 fichiersl09_*. Ce n’est pas encore une exécution de la CI sur trois OS. - Puis dans la CI : le run 37061776660 du workflow C# for beginners examples, sur le commit
690201dde la PR #113, a réussi sousubuntu-latest,windows-latestetmacos-latest. Chaque job afficheokpour les 18 fichiersl09_*; les jobs comptent 121 lignesoksous Linux et macOS et 120 sous Windows, pour la même raison qu’à la leçon 6. - Mesuré avant d’écrire :
- C# 14 n’a pas d’expression de dictionnaire.
Dictionary<string, int> d = ["C": 0, "E": 4];donne CS1003 et huit autres erreurs de syntaxe, donc la leçon utilise un initialiseur d’index,{ ["C"] = 0 }. Firstsans correspondance lèveSequence contains no matching element. Cette sonde est restée hors du code du cours.- Les deux expériences sur les dictionnaires du tableau. La documentation appuie les deux : « The order in which the items are returned is undefined », et
Remove« may be safely called without invalidating active enumerators » depuis .NET Core 3.0.
- C# 14 n’a pas d’expression de dictionnaire.
- Dogfooding au commit
5c3a52ade GA, avec l’hypothèse écrite avant de mesurer dans le tableau des expériences :- Un relevé des collections dans le code de GA, lu à ce commit, a fourni les exemples de la leçon :
ChordVocabulary.PitchClasses(ChordVocabulary.cs:23), un dictionnaire insensible à la casse lu avecTryGetValue, où"C#"et"Db"donnent tous deux 1. Ses remarques disent que deux copies antérieures « had drifted » (avaient divergé) ; ungit grepde["Db"] = 1ou{ "Db", 1 }trouve 18 fichiers avec leur propre table, celui-ci compris.PitchClassSet, unIReadOnlySet<PitchClass>construit sur unImmutableSortedSet(PitchClassSet.cs:37), égal à un autre quand leursId, calculés à partir des notes, le sont.
MusicalKnowledgeService.GetArtistBreakdowngardeGetAllArtists().Take(20), les 20 premiers par nom, puis les trie par nombre d’entrées dans unDictionary. Je m’attendais à plus de 20 artistes, et à des artistes écartés qui ont plus d’entrées qu’un artiste gardé.artists.cs, compilé avecGA.Domain.Servicesextrait pargit archivedans le dossier.gaignoré, en a trouvé 16 : aucun n’est écarté. Deux exécutions ont donné la même sortie.- La raison est la première ligne QA du jour : trois des quatre fichiers YAML ne se désérialisent pas, et chaque chargeur attrape l’exception et garde un élément par défaut. La sonde affiche les messages des chargeurs. Un test de désérialisation, hors du code du cours, a localisé les trois lignes, et j’ai lu chacune face à la classe qu’elle remplit. Les trois lignes sont inchangées sur le
mainde GA,ae196bf, le plus récent que connaît le clone local. MusicalKnowledgeServiceTestsafficheArtistBreakdown.Take(5)sous=== Top Artists ===(MusicalKnowledgeServiceTests.cs:51), ce qui dépend aussi de l’ordre du dictionnaire.
- Un relevé des collections dans le code de GA, lu à ce commit, a fourni les exemples de la leçon :
2026-10-03 — Un schéma du manche dessiné en C#
Section intitulée « 2026-10-03 — Un schéma du manche dessiné en C# »- La leçon 3 montre maintenant les notes des cases 0 à 5 sous forme de schéma, sous la sortie de
l03_fretboard.cs. La question était de savoir si ComfyUI ou Blender devaient dessiner certaines images du cours. Une image générée peut se tromper sur le nombre de cordes ou de cases, et ce schéma doit montrer exactement les notes que le programme affiche : c’est donc un programme C# qui le dessine,tools/fretboard.cs, avec les mêmes cordes à vide et les mêmes noms de notes que la leçon. - Le SVG ne contient aucun mot, seulement des noms de notes et des nombres, donc les trois langues partagent un seul fichier,
src/assets/csharp-beginner/l03-fretboard.svg. La leçon l’importe comme un composant, comme le cours de théorie musicale, pour qu’il suive le thème clair ou sombre. La leçon 3 est devenue un fichier.mdxpour cela ; son adresse ne change pas. La description pour les lecteurs d’écran est traduite. check.shlancetools/fretboard.cs -- --check, qui échoue si le SVG du dépôt diffère de ce que le programme dessine. Avant de m’y fier, j’ai changé une note du fichier à la main : la vérification a affichéis not up to dateet s’est terminée avec le code 1. Une copie avec des fins de ligne Windows passe. Sous Windows,check.shaffiche maintenant 121 lignesok.- L’outil trouve le dépôt à partir de son propre dossier,
AppContext.GetData("EntryPointFileDirectoryPath"), et non du dossier courant, et écrit chaque coordonnée comme unint: avec la culturefr-FR,$"{2.5}"donne2,5. Les deux points comptent pour les fichiers, le sujet de la leçon 10. - Rendu avec Edge sans fenêtre dans une page claire, une page sombre et à 343 pixels de large, la largeur d’un téléphone : les 36 notes correspondent ligne par ligne à la sortie du programme. Ce jour-là, Chrome sans fenêtre et la capture par DevTools ont tous deux dépassé leur délai sur cette machine.
- Puis dans la CI : le run 37142282699 du workflow C# for beginners examples, sur le commit
9229f15de la PR #126, a réussi sousubuntu-latest,windows-latestetmacos-latest. Chaque job afficheok fretboard svg; les jobs comptent 122 lignesoksous Linux et macOS et 121 sous Windows, pour la même raison qu’à la leçon 6.
2026-10-03 — Fichiers et texte
Section intitulée « 2026-10-03 — Fichiers et texte »- La leçon 10 est écrite en trois langues :
File,Path, le dossier courant, les sauts de ligne, un fichier CSV, les nombres et les cultures, les flux etusing, les encodages, et ce que Guitar Alchemist fait de ses fichiers. Elle a 11 exemples, 4 exercices et 3 extraits refusés, chacun comparé àexpected/parcheck.sh. La leçon est un fichier.mdx, pour les onglets qui montrent un chemin sur chaque OS. data/ga-projects.csvest nouveau : les douze projets de la leçon 4 avec leurs nombres de fichiers.cset.fsau commit5c3a52ade GA, comptés avecgit ls-treedans le dossier de chaque projet. Il réserve deux surprises.GA.Business.Config, un projet F#, contient 8 fichiers C#, les services rencontrés à la leçon 9.GA.Presentationn’a aucun fichier source, seulement son.csproj..gitattributesdonne à*.csvdes fins de ligne LF, pour que le fichier soit le même sur chaque OS.- Huit hypothèses ont été écrites avant de mesurer, et les huit sont confirmées (tableau des expériences). Deux n’étaient pas à l’aveugle : l’écriture de
tools/fretboard.cs, plus tôt le même jour, avait montréEntryPointFileDirectoryPath, et$"{2.5}"avecfr-FR. L’hypothèse E14 vient de la lecture de GA par un sous-agent, avant que je liseScaleVideoUrlByIdmoi-même. check.shexécutel10_where.csune seconde fois depuis la racine du dépôt et compare sa sortie àexpected/l10_where_root.txt: la CI vérifie ainsi sur trois OS que le même programme manque son fichier depuis un autre dossier. La racine n’a pas deglobal.json: là, sur ma machine,dotnetchoisit le SDK 11.0.100 en préversion au lieu du 10.0.112, un autre choix fait par le dossier courant. La sortie est la même.TextFieldParsera compilé avecusing Microsoft.VisualBasic.FileIO;et sans package : il est fourni avec .NET.- La sonde
files.csexécute les chargeurs de GA trois fois, comme le décrit son README : telle que compilée, après suppression des fichiers YAML à côté d’elle, et depuis la racine du code de GA extrait. Sa compilation affiche IL3000 sur son propre usage deAssembly.Location, l’appel dont dépend le repli deScaleVideoUrlById: dans une application en fichier unique, il renvoie une chaîne vide. - Six nouvelles lignes QA viennent de la sonde et de la lecture du code de GA qui gère ses fichiers. Un sous-agent a listé les candidats ; j’ai relu les lignes de chacun au commit
5c3a52aavant de l’écrire. Deux de ces lignes sont lues dans le code seulement, pas exécutées. - L’échec de chargement des YAML de la leçon 9 est maintenant GuitarAlchemist/ga#797, déposée le 2026-10-03 avec des liens épinglés sur le
mainde GA,ba3b9ac, où les trois lignes sont inchangées. - Sous Windows avec le SDK 10.0.112,
check.shse termine avec le code 0 et 140 lignesok, dont les 19 de la leçon 10. Ce n’est pas encore une exécution de la CI sur trois OS. - Puis dans la CI : le run 37145323198 du workflow C# for beginners examples, sur le commit
8b9fc03de la PR #129, a réussi sousubuntu-latest,windows-latestetmacos-latest. Chaque job afficheokpour les 19 vérificationsl10_*, dont l’exécution depuis la racine du dépôt ; les jobs comptent 141 lignesoksous Linux et macOS et 140 sous Windows, pour la même raison qu’à la leçon 6.
2026-10-03 — Tests unitaires
Section intitulée « 2026-10-03 — Tests unitaires »- La leçon 11 est écrite en trois langues : un test à la main, une bibliothèque et un projet de test,
[Fact]etdotnet test,[Theory], quatre tests qui échouent exprès, un objet par test, la surface publique, et les tests de Guitar Alchemist. Le code est dansl11-tests: la bibliothèqueFretboard, avec des méthodes des leçons 4, 8 et 10 inchangées ;Fretboard.Tests, 26 tests avec les solutions des exercices ;Pitfalls.Tests, 6 tests dont 4 échouent exprès.examples/l11_by_hand.csetcompile_fail/l11_private.cstournent avec les autres fichiers. - Les projets viennent de
dotnet new classlib,dotnet new xunitetdotnet add reference, lancés dans le dossier du cours ; la leçon cite leurs messages. Le modèle crée un projet xUnit v2, alors que le site de xUnit dit que la v2 est en maintenance et encourage la v3. check.shlancedotnet testsur les deux projets de test aprèsdotnet clean, pour que les avertissements de la compilation s’affichent à chaque fois, et garde un résumé : les avertissements, chaque test en échec et son message, la dernière ligne. Il retire les chemins, les durées et les piles d’appels, et trie les tests en échec par nom : xUnit a signalé les quatre échecs dans un autre ordre que celui du fichier. Les flèches↓et↑d’un échec sur une collection ont traversé Git Bash sous Windows ; la CI dira si c’est le cas sur les trois OS.- Sept hypothèses ont été écrites avant de mesurer, et les sept sont confirmées (tableau des expériences). Les deux dernières ont été écrites après lecture du fichier de test de GA et de son bootstrap, avant de les exécuter.
- Observé sans hypothèse : depuis un projet de test, un membre de bibliothèque marqué
internaldonne CS0117, « does not contain a definition », et non CS0122, dans une paire de projets d’essai ; l’analyseur du packagexunitsignale les arguments inversés (xUnit2000) avant que les tests tournent. - Le premier échec de la leçon est une vérification à la main :
FretFrequency(246.94, 1)donne 261.62, et une table donne 261.63 pour le do central, parce que la corde de si à vide est déjà arrondie. Le programme se termine quand même avec le code 0, ce qui motive un framework. - La sonde
knowledge-testsest un projet NUnit qui compile sans changement quatre fichiers de GA.Business.Core.Tests extraits du code :MusicalKnowledgeServiceTests.cs,TestEnvironment.cs,GlobalUsings.csetAssemblyInfo.cs, avec les versions de packages de ce projet.ProbeTests.csest son seul fichier propre. Sa compilation n’affiche que IDE0028 dansScaleMetadataRegistry.csde GA. Son exécution : 9 tests, 6 réussis (les 5 de GA et celui de la sonde), 3 ignorés. - Cela répond à la question ouverte du journal : aucun test de GA n’échoue quand un fichier YAML de
GA.Business.Configcesse de se charger. La question est retirée de la liste plus bas. - Sous Windows avec le SDK 10.0.112,
check.shse termine avec le code 0 et 144 lignesok, dont les 4 de la leçon 11. Ce n’est pas encore une exécution de la CI sur trois OS. - Puis dans la CI : le run 37170066128 du workflow C# for beginners examples, sur le commit
c3427a9de la PR #135, a réussi sousubuntu-latest,windows-latestetmacos-latest. Chaque job afficheokpour les 4 vérificationsl11_*; les jobs comptent 145 lignesoksous Linux et macOS et 144 sous Windows, pour la même raison qu’à la leçon 6.l11_Pitfalls.Testsréussit aussi sous Windows : les flèches↓et↑de l’échec sur une collection traversent Git Bash sans changement.
2026-10-03 — Un petit projet
Section intitulée « 2026-10-03 — Un petit projet »- La leçon 12 est écrite en trois langues : une solution avec la bibliothèque de la leçon 11, une application console et un projet de test ; les codes de sortie ; un package NuGet dans une application basée sur un fichier et dans la bibliothèque ; un package qui a une vulnérabilité connue ;
dotnet pack; un premier regard surasync; et la solution, les versions de packages, l’outil en ligne de commande et les attentes bloquantes de Guitar Alchemist. Le code est dansl12-project:Fretboard, la bibliothèque de la leçon 11 avecGuitarinchangé,ProjectsansParse, etProjectFile, qui lit le fichier CSV avec CsvHelper 33.1.0 ;Fretboard.App, avec trois commandes ;Fretboard.Tests, 6 tests. Quatre exemples, deux extraits refusés et quatre solutions d’exercices sont des applications basées sur un fichier. check.shempaquette la bibliothèque avant la boucle, puisqueexercises/l12_ex_package.cslit le package, et supprime d’abord l’ancien package : sans changement,dotnet packle garde et n’affiche aucune de ses deux lignes. Il lancedotnet testsur la solution aprèsdotnet cleanet vérifie que l’application console n’est toujours pas compilée, puisdotnet build, dont il réduit la sortie aux noms des projets, triés, et aux totaux. Il lance l’application avec six commandes et affiche chaque code de sortie. Une nouvelle règlesedretire le dossier des messages NuGet d’une ligne#:package,file.csproj : warning NUxxxx.- Douze hypothèses sur le SDK et neuf sur GA ont été écrites avant de mesurer, certaines après avoir lu le code qu’elles testent (tableau des expériences) : 16 confirmées, 1 partiellement réfutée, 2 réfutées. Les réfutées portent sur les attentes de GA : 11 attentes bloquantes compilées, pas 20 ou plus, et aucun
async void. - Observé sans hypothèse :
dotnet testsur une solution ne compile pas l’application console, ce qui a mené à l’hypothèse sur une erreur de compilation ; l’avertissement de l’audit NuGet sort deux fois dans une application basée sur un fichier ; le.nuspecenregistre le commit deHEAD; 12 des 28 commandes de GaCLI lèventNotImplementedException, et le run 37167745677 de Quality Check de GA est vert avec une étape terminée par le code de sortie 134. - Les sondes sont dans
ga-probes:lesson12_counts.pylit le commit avecgitseulement, etlesson12-results.txtgarde sa sortie ; la compilation deGA.Business.Core.Graphiti.Testset sa restauration, avec une copie témoin dont la ligneUpdateest dansDirectory.Build.targets; GaCLI, compilé à partir des 18 projets de ses références en 28 s avec 21 avertissements, et lancé depuis deux dossiers. - Cela règle le point à vérifier sur GaCLI lancé depuis un autre dossier : il tourne, et à ce commit
appsettings.yamlne change rien. Le point est retiré de la liste ci-dessous, et la ligne du tableau QA est mise à jour. - Sous Windows avec le SDK 10.0.112,
check.shse termine avec le code 0 et 158 lignesok, dont les 14 de la leçon 12. Ce n’est pas encore une exécution de la CI sur trois OS. - La première exécution de la CI de la PR, 37174610693, a échoué sur
l12_auditetl12_package_no_versionsur les trois OS, et a passé les 12 autres vérifications de la leçon 12. La CI utilise le SDK 10.0.401, queglobal.jsonautorise (rollForward: latestFeature), et ce SDK nomme le projet caché derrière une application basée sur un fichierl12_audit.cs.csproj, là où le 10.0.112 ditl12_audit.csproj. La règlesedn’attendait pas de point dans le nom et laissait le dossier.check.shécrit maintenantfile.csprojpour les deux, et la leçon donne les deux noms. - Puis dans la CI : le run 37175088215 du workflow C# for beginners examples, sur le commit
87dbafdde la PR #137, a réussi sousubuntu-latest,windows-latestetmacos-latest, tous trois avec le SDK 10.0.401. Chaque job afficheokpour les 14 vérificationsl12_*; les jobs comptent 159 lignesoksous Linux et macOS et 158 sous Windows, pour la même raison qu’à la leçon 6. L’avertissement de l’audit NuGet del12_audit.cssort sur les trois machines, et la sortie triée de la compilation est la même.
2026-10-04 — Correctifs proposés à Guitar Alchemist
Section intitulée « 2026-10-04 — Correctifs proposés à Guitar Alchemist »Treize lignes du tableau QA sont reparties vers GA sous forme de cinq pull requests, ouvertes depuis un clone séparé à main 75959835. Chacune mesure le défaut avant et après le correctif, et la CI de GA passe sur les cinq. Aucune n’est encore fusionnée : GA laisse la relecture et la fusion à quelqu’un d’autre que l’auteur.
| PR | Lignes QA | Changement | Avant → après |
|---|---|---|---|
| n° 808 | Les trois fichiers YAML (issue n° 797) ; les tests qui ne voient pas une valeur de repli | Les trois fichiers se chargent ; les trois tests [Ignore] s’exécutent, et un nouveau test échoue quand un fichier retombe sur son élément par défaut |
Avec les anciens fichiers, 5 des 9 tests échouent, le nouveau avec Expected: greater than 1 But was: 1 pour chaque fichier cassé |
| n° 811 | ReloadConfiguration, GetArtistBreakdown, la culture du CSV, son nombre de lignes, sync-mongodb |
Un nouveau Lazy au lieu de FieldInfo.SetValue ; le tri avant Take(20) ; FormattableString.Invariant ; l’en-tête hors du compte ; Environment.Exit(1) |
FieldAccessException → les quatre fichiers se rechargent ; < 6, 8, 8, … > valeurs par ligne sous fr-FR → 6 ; 3 lignes comptées pour un en-tête et deux lignes → 2 ; sync-mongodb sort avec 0 → 1 |
| n° 812 | Les projets de test hors de AllProjects.slnx, les éléments PackageReference Update, le scan de sécurité |
Les éléments passent dans Directory.Build.targets ; trois projets de test rejoignent la solution ; le scan échoue sur un avis qu’une ligne de base ne liste pas |
Rétrogradations NU1605 masquées par NoWarn : 80 → 40 ; 56 tests de plus en CI ; 21 avis dans la ligne de base |
| n° 816 | Le ToString d’un modèle d’accord, le [SetUpFixture] |
ChordTemplate.ToString devient sealed ; TestEnvironment passe dans l’espace de noms racine du projet |
Un vidage de 442 ou 475 caractères → le nom ; GA_TEST_MODE absent → 1, avec la racine du dépôt comme répertoire courant |
| n° 817 | ScaleVideoUrl |
GA.Domain.Core.csproj incorpore scale_video_urls.json, et ScaleVideoUrlById le lit sous son nom par défaut |
Ensembles avec une URL de vidéo : 0 → 1 490 sur 4 096 |
- Avec le YAML de la n° 808, GA compte 63 artistes au lieu de 16 : la coupe de
GetArtistBreakdownavant le tri se voit, et le test de la n° 811 sur cette répartition échoue sur ces données avec l’ancien code. - Déplacer seuls les éléments
Updatefaisait échouer la restauration,error NU1107: Version conflict detected for Microsoft.Extensions.Logging.Abstractionsdans GA.Infrastructure, car cinq packages Microsoft.Extensions seulement étaient alignés. La n° 812 met les 19 qui sont livrés avec .NET et ASP.NET Core à une seule version, 10.0.6, la plus haute que demande un projet ou un package. - Trois des six projets de test hors de la solution, qu’aucun workflow ne nomme, y entrent : les tests Graphiti, avec la référence de projet qui leur manquait, ceux de ProbabilisticGrammar et ceux de TabConversion.Api.
GaChatbot.TestsetTests/GaApi.Testsne compilent pas non plus surmain, etFloorManager.Tests.Playwrighta besoin d’un FloorManager lancé. - Le contrôle
risk-reportde GA échoue sur la n° 812 par construction : sa politique interdit à un agent de modifier.github/workflowset classeDirectory.Build.*,*.csprojet*.slnxparmi les décisions irréversibles ; un mainteneur doit donc la relire. - La n° 817 modifie un
.csproj, que la politique de risque de GA compte comme une porte à sens unique : c’est donc une pull request à part. - La première exécution de la CI de la n° 816 a échoué sur un test d’un autre projet, qui laisse 10 secondes à PowerShell ; le même test avait échoué sur une autre branche le 2026-05-23, et la relance est passée.
2026-10-06 — Les PR 816 et 817 de GA, revérifiées
Section intitulée « 2026-10-06 — Les PR 816 et 817 de GA, revérifiées »Les PR n° 816 et n° 817 de GA sont toujours ouvertes, sans revue ni commentaire. Leur CI passe, 16 vérifications dont 5 ignorées, et GitHub les dit toutes deux fusionnables sans conflit, bien que le main de GA ait avancé de 14 commits depuis leur base, jusqu’à 40d33747. Lus par l’API GitHub, les trois défauts n’ont pas changé à ce commit :
- Le
ToString() => NamedeChordTemplaten’est toujours passealed(ChordTemplate.cs:84). ScaleVideoUrlByIdlit toujours la ressourceGA.Domain.Core.Scales.Data.scale_video_urls.jsonet le chemin de repliScales/Data/(ScaleVideoUrlById.cs:30, :38), etGA.Domain.Core.csprojne nomme toujours pas le fichier.TestEnvironmentest toujours seul dansGA.Business.Core.Tests.TestBootstrap(TestEnvironment.cs:1).
La leçon 7 montre maintenant le piège de ToString à côté de ChordTemplate, avec examples/l07_record_tostring.cs. Un record dérivé affiche Seventh { Name = Major 7th, Quality = Major 7th } ; le même record sous une base dont le ToString est sealed affiche Major 7th. Les deux sorties viennent du SDK 10.0.112, comparées à expected/ comme le fait check.sh. L’exemple existant l07_inheritance.cs, lancé de la même façon, correspond toujours à sa sortie attendue. Les sondes GA n’ont pas été relancées : elles demandent une copie de GA hors du code du cours. check.sh non plus n’a pas été lancé en entier.
À vérifier
Section intitulée « À vérifier »- Le nombre d’artistes que GA compterait une fois ses trois fichiers YAML chargés. Un script PyYAML sur les fichiers bruts, hors du code du cours, l’estime à 63. Selon la même estimation,
Take(20)écarterait 8 artistes qui ont plus d’entrées que le plus petit nombre gardé, dont The Beatles (3 entrées). - Les commandes d’installation pour Linux et macOS : seul le
setup-dotnetde la CI a tourné sur ces OS. - La démonstration du débogueur de la leçon 3 dans VS Code, Visual Studio et Rider, pour une application basée sur un fichier et pour un projet. VS Code 1.118 et Rider sont installés sur ma machine ; Visual Studio ne l’est pas.
- Les conditions de licence des trois éditeurs, au moment de la lecture.
Questions ouvertes
Section intitulée « Questions ouvertes »- Les autres projets de GA, au-delà de GA.Domain.Core et GA.Core, ont-ils des avertissements de nullabilité que les deux listes
NoWarncachent ? Seuls ces deux-là ont été mesurés (2026-10-02).