ASCII Table — C# source
A searchable, filterable reference for all 128 ASCII code points. See the decimal, hex, octal, and binary form of every character, narrow to printable characters only, clamp the code-point range, and click any row to copy. Runs 100% client-side.
This is the C# implementation — the same logic the interactive tool runs, in a shareable, citable form.
// ASCII Table — pure logic (C# port): the 128-entry ASCII reference table with
// search and range filters.
//
// Language: C# 12 (.NET 8) — standard library only (System, System.Collections.Generic, System.Linq).
// Source: CosmoDev polyglot showcase port; canonical = src/lib/ascii-table.ts
// + this tool's python.py / rust.rs.
// License: display source — part of CosmoDev's polyglot tool pages.
//
// Each of the 128 ASCII code points is described by its decimal / hex / octal /
// binary forms, a display glyph, a human name, whether it is printable, whether
// it is a control character, and (for control chars that have one) a C-style
// escape sequence.
#nullable enable
namespace CosmoDev.AsciiTable;
/// <summary>A single ASCII code point and its derived representations.</summary>
/// <param name="Dec">Decimal code point, 0–127.</param>
/// <param name="Hex">Uppercase hex, e.g. "0x41".</param>
/// <param name="Oct">Zero-padded 3-digit octal, e.g. "101".</param>
/// <param name="Binary">Zero-padded 8-bit binary, e.g. "01000001".</param>
/// <param name="Glyph">Display glyph: the literal char for printables, a control-picture
/// glyph otherwise. (Named <c>char</c> in the canonical sources; that is a keyword here.)</param>
/// <param name="Name">Human-readable name, e.g. "Line Feed (LF)", "Uppercase A", "Space".</param>
/// <param name="Printable">True for 32–126 (visible or space).</param>
/// <param name="Control">True for 0–31 and 127.</param>
/// <param name="Escape">C-style escape for control chars that have one (e.g. "\n"); null otherwise.</param>
public sealed record Entry(
int Dec,
string Hex,
string Oct,
string Binary,
string Glyph,
string Name,
bool Printable,
bool Control,
string? Escape = null);
/// <summary>The <c>ascii-table</c> tool's pure logic.</summary>
public static class AsciiTable
{
/// <summary>
/// Official ASCII control-character names for 0–31 and 127. Expressed as a
/// switch expression over every control code point; the discard arm is a
/// defensive guard that documents the precondition (the Rust port uses
/// unreachable!() for the same case).
/// </summary>
private static string ControlName(int code) => code switch
{
0 => "Null (NUL)",
1 => "Start of Heading (SOH)",
2 => "Start of Text (STX)",
3 => "End of Text (ETX)",
4 => "End of Transmission (EOT)",
5 => "Enquiry (ENQ)",
6 => "Acknowledge (ACK)",
7 => "Bell (BEL)",
8 => "Backspace (BS)",
9 => "Horizontal Tab (HT)",
10 => "Line Feed (LF)",
11 => "Vertical Tab (VT)",
12 => "Form Feed (FF)",
13 => "Carriage Return (CR)",
14 => "Shift Out (SO)",
15 => "Shift In (SI)",
16 => "Data Link Escape (DLE)",
17 => "Device Control 1 (DC1)",
18 => "Device Control 2 (DC2)",
19 => "Device Control 3 (DC3)",
20 => "Device Control 4 (DC4)",
21 => "Negative Acknowledge (NAK)",
22 => "Synchronous Idle (SYN)",
23 => "End of Transmission Block (ETB)",
24 => "Cancel (CAN)",
25 => "End of Medium (EM)",
26 => "Substitute (SUB)",
27 => "Escape (ESC)",
28 => "File Separator (FS)",
29 => "Group Separator (GS)",
30 => "Record Separator (RS)",
31 => "Unit Separator (US)",
127 => "Delete (DEL)",
_ => "", // only called with control codes; defensive guard for misuse
};
/// <summary>
/// C-style escape for the control chars that own a standard/common one.
/// Returns the literal 2-character source token (backslash + letter), or null.
/// </summary>
private static string? ControlEscape(int code) => code switch
{
0 => "\\0",
7 => "\\a",
8 => "\\b",
9 => "\\t",
10 => "\\n",
11 => "\\v",
12 => "\\f",
13 => "\\r",
27 => "\\e",
_ => null,
};
/// <summary>
/// Name for a printable punctuation / symbol glyph, or null.
/// Letters and digits are derived in <see cref="LetterName"/>.
/// </summary>
private static string? SymbolName(int code) => code switch
{
32 => "Space",
33 => "Exclamation mark",
34 => "Quotation mark",
35 => "Number sign",
36 => "Dollar sign",
37 => "Percent sign",
38 => "Ampersand",
39 => "Apostrophe",
40 => "Left parenthesis",
41 => "Right parenthesis",
42 => "Asterisk",
43 => "Plus sign",
44 => "Comma",
45 => "Hyphen / Minus",
46 => "Full stop",
47 => "Slash",
58 => "Colon",
59 => "Semicolon",
60 => "Less-than sign",
61 => "Equals sign",
62 => "Greater-than sign",
63 => "Question mark",
64 => "At sign",
91 => "Left bracket",
92 => "Backslash",
93 => "Right bracket",
94 => "Circumflex / Caret",
95 => "Underscore",
96 => "Grave accent",
123 => "Left brace",
124 => "Vertical bar",
125 => "Right brace",
126 => "Tilde",
_ => null,
};
/// <summary>Derive a name for a printable letter or digit.</summary>
private static string LetterName(int code) => code switch
{
>= 48 and <= 57 => $"Digit {code - 48}", // '0'..'9'
>= 65 and <= 90 => $"Uppercase {(char)code}", // 'A'..'Z'
>= 97 and <= 122 => $"Lowercase {(char)code}", // 'a'..'z'
_ => ((char)code).ToString(),
};
/// <summary>Build a single entry from its code point (0–127).</summary>
private static Entry MakeEntry(int code)
{
bool control = code <= 31 || code == 127;
// Control-picture glyph: U+2400 for 0–31, U+2421 ("symbol for delete") for DEL.
string glyph = control
? char.ConvertFromUtf32(code == 127 ? 0x2421 : 0x2400 + code)
: ((char)code).ToString();
string name = control ? ControlName(code) : SymbolName(code) ?? LetterName(code);
return new Entry(
Dec: code,
Hex: $"0x{code:X2}",
Oct: Convert.ToString(code, 8).PadLeft(3, '0'),
Binary: Convert.ToString(code, 2).PadLeft(8, '0'),
Glyph: glyph,
Name: name,
Printable: !control,
Control: control,
Escape: control ? ControlEscape(code) : null);
}
// The 128-entry table is built once in the type initializer; .NET guarantees
// type initializers run exactly once, thread-safely — the CLR equivalent of
// Rust's OnceLock.
private static readonly Entry[] _entries = BuildTable();
private static Entry[] BuildTable()
{
var table = new Entry[128];
for (int i = 0; i < 128; i++)
table[i] = MakeEntry(i);
return table;
}
/// <summary>The full 128-entry ASCII table, indexed by code point.</summary>
public static IReadOnlyList<Entry> Entries => _entries;
/// <summary>
/// Look up a single entry by code point. Returns null for out-of-range
/// input (the TypeScript variant returns null; C#'s nullable reference
/// type annotation carries the same contract).
/// </summary>
public static Entry? GetEntry(int code) => code >= 0 && code <= 127 ? _entries[code] : null;
/// <summary>
/// Filter the table.
///
/// <paramref name="query"/> is a case-insensitive substring matched against
/// dec / hex / oct / binary / name / char / escape.
/// <paramref name="printableOnly"/> hides controls.
/// <paramref name="min"/> / <paramref name="max"/> clamp the decimal range (defaults 0–127).
/// </summary>
public static List<Entry> FilterTable(string query = "", bool printableOnly = false,
int min = 0, int max = 127)
{
string q = (query ?? "").Trim().ToLowerInvariant();
List<Entry> result = new();
foreach (Entry e in _entries)
{
if (printableOnly && !e.Printable)
continue;
if (e.Dec < min || e.Dec > max)
continue;
if (q.Length > 0)
{
bool hit = e.Dec.ToString().Contains(q)
|| e.Hex.ToLowerInvariant().Contains(q)
|| e.Oct.Contains(q)
|| e.Binary.Contains(q)
|| e.Name.ToLowerInvariant().Contains(q)
|| e.Glyph.ToLowerInvariant().Contains(q)
|| (e.Escape ?? "").Contains(q);
if (!hit)
continue;
}
result.Add(e);
}
return result;
}
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →