Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d5f6656
fix(ci): restore validation for the Chinese edition
transbot Nov 10, 2026
52a9b3c
ci: record SDK and runtime inventories in every validation job
transbot Nov 10, 2026
3158071
fix(ci): run SDK analysis without the obsolete Guardian runtime
transbot Nov 10, 2026
c1fd992
ci: finish both locale jobs even when one reports test failures
transbot Nov 10, 2026
410ad2b
ci: validate stacked Chinese test repairs with manual merging
transbot Nov 10, 2026
0af850f
fix(encoding): preserve Chinese listings as UTF-8 across platforms
transbot Nov 10, 2026
b16482a
test(zh): align introductory chapters with the Chinese manuscript
transbot Nov 10, 2026
745b781
test(zh): adapt object, LINQ, reflection and concurrency examples
transbot Nov 10, 2026
cb4118c
test(zh): preserve quadrant cases and finish assertion audit
transbot Nov 10, 2026
58af8b0
test(zh): verify exact Chinese listing output across locales
transbot Nov 10, 2026
9dc192c
fix(zh): follow the Chinese manuscript for listing 5.12
transbot Nov 10, 2026
4f81e05
ci: execute probes to verify actual runtimes for every target
transbot Nov 10, 2026
f615f70
Merge branch 'codex/restore-chinese-branch-ci' into codex/adapt-chine…
transbot Nov 10, 2026
716d238
test(zh): capture PowerShell UTF-8 output without pipe deadlocks
transbot Nov 10, 2026
98b8b84
ci: enforce UTF-8 for every tracked text file
transbot Nov 10, 2026
f606d79
Merge branch 'codex/restore-chinese-branch-ci' into codex/adapt-chine…
transbot Nov 10, 2026
379e353
docs(zh): repair a previously corrupted project comment
transbot Nov 10, 2026
84b98ae
test(zh): cover Chinese child output and full stderr pipes
transbot Nov 10, 2026
49f6034
test(zh): verify the Chinese processor ID label on Windows
transbot Nov 10, 2026
fabdf57
Merge pull request #63 from transbot/codex/adapt-chinese-tests
transbot Nov 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ root = true
# All files
[*]
indent_style = space
charset = utf-8

# Keep legacy Windows PowerShell able to recognize Chinese script text.
[*.ps1]
charset = utf-8-bom

# Xml files
[*.xml]
Expand Down Expand Up @@ -367,4 +372,4 @@ spelling_checkable_types = strings,identifiers,comments
spelling_error_severity = error

# Custom Rules
dotnet_diagnostic.IDE0036.severity = warning
dotnet_diagnostic.IDE0036.severity = warning
6 changes: 5 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,8 @@

# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary
*.jpg binary
*.pdf binary
*.docx binary
*.dll binary
*.encrypt binary
34 changes: 34 additions & 0 deletions .github/actions/report-dotnet-runtime/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Report selected .NET runtimes
description: Execute a small probe for every target framework declared by Common.props
runs:
using: composite
steps:
- name: Execute runtime probes
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
$probeDirectory = Join-Path $env:RUNNER_TEMP ("dotnet-runtime-probe-" + [Guid]::NewGuid().ToString('N'))
New-Item -ItemType Directory -Path $probeDirectory | Out-Null
Copy-Item (Join-Path $env:GITHUB_WORKSPACE 'global.json') $probeDirectory
$commonPath = Join-Path $env:GITHUB_WORKSPACE 'Common.props'
$escapedCommonPath = [System.Security.SecurityElement]::Escape($commonPath)
$project = "<Project Sdk=`"Microsoft.NET.Sdk`"><Import Project=`"$escapedCommonPath`" /><PropertyGroup><OutputType>Exe</OutputType></PropertyGroup></Project>"
Set-Content (Join-Path $probeDirectory 'RuntimeProbe.csproj') $project -Encoding utf8
$source = @'
System.Console.WriteLine($"Actual runtime: {System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription}; version={System.Environment.Version}; architecture={System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture}");
'@
Set-Content (Join-Path $probeDirectory 'Program.cs') $source -Encoding utf8
Push-Location $probeDirectory
try {
Write-Host "Probe SDK: $(dotnet --version)"
dotnet build RuntimeProbe.csproj --verbosity quiet
if ($LASTEXITCODE -ne 0) { throw "Runtime probe build failed: $LASTEXITCODE" }
$frameworks = ([xml](Get-Content $commonPath -Raw)).Project.PropertyGroup.TargetFrameworks.Split(';')
foreach ($framework in $frameworks) {
Write-Host "Target framework: $framework"
dotnet (Join-Path $probeDirectory "bin/Debug/$framework/RuntimeProbe.dll")
if ($LASTEXITCODE -ne 0) { throw "Runtime probe failed for ${framework}: $LASTEXITCODE" }
}
} finally {
Pop-Location
}
37 changes: 37 additions & 0 deletions .github/scripts/check_utf8.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""Validate every tracked text file; Git attributes identify binary assets."""

from pathlib import Path
import subprocess
import sys


def main() -> int:
names = subprocess.check_output(["git", "ls-files", "-z"])
attributes = subprocess.check_output(
["git", "check-attr", "-z", "--stdin", "text"], input=names
).split(b"\0")
binary = {
attributes[i]
for i in range(0, len(attributes) - 1, 3)
if attributes[i + 2] == b"unset"
}
checked = 0
failures = []
for name in filter(None, names.split(b"\0")):
if name in binary:
continue
path = Path(name.decode("utf-8"))
try:
path.read_bytes().decode("utf-8-sig")
except UnicodeDecodeError as error:
failures.append(f"{path.as_posix()}: invalid UTF-8 at byte {error.start}")
checked += 1
if failures:
print("UTF-8 validation failed:", *failures, sep="\n")
return 1
print(f"UTF-8 validated: {checked} tracked text files; {len(binary)} binary assets excluded.")
return 0


if __name__ == "__main__":
sys.exit(main())
49 changes: 39 additions & 10 deletions .github/workflows/Code-Analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: .NET Code Analysis

on:
push:
branches: [ 'v[1-9][0-9].0' ]
branches: [ 'v[1-9][0-9].0', 'v12.0Chinese' ]
pull_request:
branches: [ 'v[1-9][0-9].0' ]
branches: [ 'v[1-9][0-9].0', 'v12.0Chinese', 'codex/restore-chinese-branch-ci' ]

jobs:
NET-Code-Analysis:
Expand All @@ -14,10 +14,24 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Verify repository text encoding
shell: pwsh
run: python -X utf8 .github/scripts/check_utf8.py
- name: Setup dotnet SDK
uses: actions/setup-dotnet@v4
with:
global-json-file: global.json
dotnet-version: |
6.0.x
7.0.x
- name: Get Build Information
run: |
dotnet --info
dotnet --version
dotnet --list-sdks
dotnet --list-runtimes
- name: Verify actual target runtimes
uses: ./.github/actions/report-dotnet-runtime
- name: Set up dependency caching for faster builds
uses: actions/cache@v4
id: nuget-cache
Expand All @@ -33,17 +47,32 @@ jobs:
- name: Run NuGet restore
run: dotnet restore

# Run code analysis for the solution at repo root
# Use the SDK analyzers directly; the old Guardian wrapper requires .NET 3.1.
- name: Run .NET Code Analysis
uses: dotnet/code-analysis@main
id: code-analysis
with:
build-breaking: false
all-categories: latest
shell: bash
run: |
cat > "$RUNNER_TEMP/code-analysis.targets" <<'EOF'
<Project>
<Import Project="$(MSBuildStartupDirectory)/Directory.Build.targets" />
<PropertyGroup>
<AnalysisLogDirectory>$(MSBuildProjectDirectory)/obj/analysis/$(TargetFramework)</AnalysisLogDirectory>
<ErrorLog>$(AnalysisLogDirectory)/analysis.sarif,version=2.1</ErrorLog>
</PropertyGroup>
<Target Name="CreateAnalysisLogDirectory" BeforeTargets="CoreCompile">
<MakeDir Directories="$(AnalysisLogDirectory)" />
</Target>
</Project>
EOF
dotnet build --no-restore \
-p:AnalysisLevel=latest \
-p:AnalysisMode=Minimum \
-p:EnforceCodeStyleInBuild=true \
-p:DirectoryBuildTargetsPath="$RUNNER_TEMP/code-analysis.targets"

# Upload the analysis results file
- name: Upload analysis results
if: always()
uses: actions/upload-artifact@v4
with:
name: analysis_results.sarif
path: ${{ steps.code-analysis.outputs.sarifFile }}
path: src/**/obj/analysis/**/*.sarif
if-no-files-found: error
19 changes: 17 additions & 2 deletions .github/workflows/LocalesTest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,38 @@ name: Test Different Locales

on:
push:
branches: [ 'v[1-9][0-9].0' ]
branches: [ 'v[1-9][0-9].0', 'v12.0Chinese' ]
pull_request:
branches: [ 'v[1-9][0-9].0' ]
branches: [ 'v[1-9][0-9].0', 'v12.0Chinese', 'codex/restore-chinese-branch-ci' ]

jobs:
set-build-and-test-locale-languages:
name: Build and Test ${{ matrix.locale-lang }} Locale On Ubuntu
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
locale-lang: ["pt_BR.UTF-8", "fr_FR.UTF-8"]
steps:
- uses: actions/checkout@v4
- name: Verify repository text encoding
shell: pwsh
run: python -X utf8 .github/scripts/check_utf8.py
- name: Setup dotnet SDK
uses: actions/setup-dotnet@v4
with:
global-json-file: global.json
dotnet-version: |
6.0.x
7.0.x
- name: Get Build Information
run: |
dotnet --info
dotnet --version
dotnet --list-sdks
dotnet --list-runtimes
- name: Verify actual target runtimes
uses: ./.github/actions/report-dotnet-runtime
- name: Set up dependency caching for faster builds
uses: actions/cache@v4
id: nuget-cache
Expand Down
16 changes: 14 additions & 2 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ name: Build and Test

on:
push:
branches: [ 'v[1-9][0-9].0' ]
branches: [ 'v[1-9][0-9].0', 'v12.0Chinese' ]
pull_request:
branches: [ 'v[1-9][0-9].0' ]
branches: [ 'v[1-9][0-9].0', 'v12.0Chinese', 'codex/restore-chinese-branch-ci' ]
schedule:
- cron: 0 6 * * 1

jobs:
automerge:
# Keep the Chinese edition's dependency updates subject to manual review.
if: github.event_name == 'pull_request' && github.base_ref != 'v12.0Chinese' && github.base_ref != 'codex/restore-chinese-branch-ci'
runs-on: ubuntu-latest

permissions:
Expand All @@ -30,15 +32,25 @@ jobs:
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@v4
- name: Verify repository text encoding
shell: pwsh
run: python -X utf8 .github/scripts/check_utf8.py
- name: Setup dotnet SDK
uses: actions/setup-dotnet@v4
with:
global-json-file: global.json
dotnet-version: |
6.0.x
7.0.x
- name: Get Build Information
run: |
pwd
dotnet --info
dotnet --version
dotnet --list-sdks
dotnet --list-runtimes
- name: Verify actual target runtimes
uses: ./.github/actions/report-dotnet-runtime
- name: Set up dependency caching for faster builds
uses: actions/cache@v4
id: nuget-cache
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# EssentialCSharp - C#本质论
# EssentialCSharp - C#本质论

本项目包含《C# 12.0本质论》的源代码,2024年清华大学出版社出版。

Expand Down Expand Up @@ -58,7 +58,9 @@

## 测试

注:中文版请忽略。
测试断言按中文版译稿及本仓库的配套示例维护,覆盖现有的 net6.0、net7.0 和 net8.0 目标框架。

部分清单刻意演示编译错误或运行时异常;对应测试会核对编译诊断或预期异常,不应为了通过测试而消除这些教学示例中的错误。

许多代码清单都有相应的单元测试。

Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "8.0.0",
"version": "8.0.100",
"rollForward": "latestFeature",
"allowPrerelease": true
}
Expand Down
4 changes: 2 additions & 2 deletions src/Chapter01.Tests/Listing01.01.Tests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using AddisonWesley.Michaelis.EssentialCSharp.Shared.Tests;
using AddisonWesley.Michaelis.EssentialCSharp.Shared.Tests;

namespace AddisonWesley.Michaelis.EssentialCSharp.Chapter01.Listing01_01.Tests;

Expand Down Expand Up @@ -27,7 +27,7 @@ public void CreateAndRunNewConsoleProject()
// produced the expected output.
Assert.IsTrue(
psOutput.Contains(
$"{Environment.NewLine}Hello. My name is Inigo Montoya.{Environment.NewLine}"),
$"{Environment.NewLine}你好,我叫Inigo Montoya。{Environment.NewLine}"),
"The expected HelloWorld output was not found.");

// If the output is in English
Expand Down
6 changes: 3 additions & 3 deletions src/Chapter01.Tests/Listing01.03.Tests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@


namespace AddisonWesley.Michaelis.EssentialCSharp.Chapter01.Listing01_03.Tests;

[TestClass]
Expand All @@ -8,8 +8,8 @@ public class HelloWorldTests
public void Main_UpDown()
{
const string expected =
@"Up
Down";
@"上
下";

IntelliTect.TestTools.Console.ConsoleAssert.Expect(
expected, HelloWorld.Main);
Expand Down
8 changes: 4 additions & 4 deletions src/Chapter01.Tests/Listing01.04.Tests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@


namespace AddisonWesley.Michaelis.EssentialCSharp.Chapter01.Listing01_04.Tests;

[TestClass]
Expand All @@ -8,9 +8,9 @@ public class HelloWorldTests
public void Main_InigoHello()
{
const string expected =
@"Down
Side
Up";
@"上
中
下";

IntelliTect.TestTools.Console.ConsoleAssert.Expect(
expected, HelloWorld.Main);
Expand Down
4 changes: 2 additions & 2 deletions src/Chapter01.Tests/Listing01.05.Tests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@


namespace AddisonWesley.Michaelis.EssentialCSharp.Chapter01.Listing01_05.Tests;

[TestClass]
Expand All @@ -8,7 +8,7 @@ public class HelloWorldTests
public void Main_InigoHello()
{
const string expected =
@"Hello. My name is Inigo Montoya.";
@"你好,我叫Inigo Montoya。";

IntelliTect.TestTools.Console.ConsoleAssert.Expect(
expected, HelloWorld.Main);
Expand Down
4 changes: 2 additions & 2 deletions src/Chapter01.Tests/Listing01.06.Tests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@


namespace AddisonWesley.Michaelis.EssentialCSharp.Chapter01.Listing01_06.Tests;

[TestClass]
Expand All @@ -8,7 +8,7 @@ public class HelloWorldTests
public void Main_InigoHello()
{
const string expected =
@"Hello. My name is Inigo Montoya.";
@"你好,我叫Inigo Montoya。";

IntelliTect.TestTools.Console.ConsoleAssert.Expect(
expected, Program.Main);
Expand Down
4 changes: 2 additions & 2 deletions src/Chapter01.Tests/Listing01.08.Tests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@


namespace AddisonWesley.Michaelis.EssentialCSharp.Chapter01.Listing01_08.Tests;

[TestClass]
Expand All @@ -7,7 +7,7 @@ public class ProgramTests
[TestMethod]
public void Main_InigoHello()
{
const string expected = @"Hello, My name is Inigo Montoya";
const string expected = @"你好,我叫Inigo Montoya。";

IntelliTect.TestTools.Console.ConsoleAssert.Expect(
expected, Program.Main);
Expand Down
Loading
Loading