Data Unit Converter — C# source
Convert between digital data units - B, KB/KiB, MB/MiB, GB/GiB, TB/TiB. Switch between decimal (1000) and binary (1024) bases, runs entirely in your browser.
This is the C# implementation — the same logic the interactive tool runs, in a shareable, citable form.
// =============================================================================
// DataUnitConverter.cs — CosmoDev polyglot showcase port of the
// `data-unit-converter` tool
// -----------------------------------------------------------------------------
// Language : C# (C# 12, standard library only)
// Source: ported from src/lib/dataUnits.ts (the canonical, live TypeScript
// lib); mirrors src/tool-sources/data-unit-converter/{python.py,rust.rs}
// License : display source — part of CosmoDev's polyglot tool pages
// (dev.cosmolabs.org). Shown verbatim alongside the JS/TS/Go/Rust/
// Python ports and the other language ports.
// -----------------------------------------------------------------------------
// Pure digital-data unit conversion. Convert between B, KB/KiB, MB/MiB,
// GB/GiB, TB/TiB: the decimal base 1000 pairs with KB/MB/GB/TB (SI) and the
// binary base 1024 with KiB/MiB/GiB/TiB (IEC). Deterministic and
// side-effect free; ConvertData returns double.NaN for non-finite input,
// unknown unit symbols, or an invalid base — never throws.
// =============================================================================
using System;
using System.Collections.Generic;
namespace CosmoDev;
/// <summary>
/// Supported conversion radix: decimal (<c>Decimal = 1000</c>, SI units) or
/// binary (<c>Binary = 1024</c>, IEC units).
/// </summary>
public enum DataBase
{
Decimal = 1000,
Binary = 1024,
}
/// <summary>
/// Pure digital-data unit conversion for the Data Unit Converter tool on
/// CosmoDev (dev.cosmolabs.org).
/// </summary>
public static class DataUnitConverter
{
/// <summary>
/// Units available under each base, ordered smallest (B) to largest. The
/// UI uses these to populate the per-base unit pickers.
/// </summary>
public static IReadOnlyList<string> UnitsFor(DataBase dataBase) => dataBase switch
{
DataBase.Decimal => new[] { "B", "KB", "MB", "GB", "TB" },
DataBase.Binary => new[] { "B", "KiB", "MiB", "GiB", "TiB" },
_ => Array.Empty<string>(),
};
/// <summary>
/// Power-of-base rank for a unit symbol, or <see langword="null"/> when
/// unknown: "B" is rank 0 and each prefix step adds 1. KB and KiB are
/// both rank 1 — the unit picks the rank, the base decides whether a rank
/// means ×1000 or ×1024 (mirrors the TS dictionary lookup).
/// </summary>
private static int? ExponentOf(string unit) => unit switch
{
"B" => 0,
"KB" or "KiB" => 1,
"MB" or "MiB" => 2,
"GB" or "GiB" => 3,
"TB" or "TiB" => 4,
_ => null,
};
/// <summary>
/// Convert a value between two digital-data units under the given base.
/// Strategy: reduce to bytes via <c>value × base^fromExp</c>, then divide
/// by <c>base^toExp</c>. Non-finite values (Inf/NaN), unknown symbols, or
/// a base other than 1000/1024 yield <see cref="double.NaN"/> — never
/// throws (mirrors the TypeScript contract).
/// </summary>
public static double ConvertData(double value, string fromUnit, string toUnit, int dataBase)
{
// Reject Inf/NaN early so they don't propagate through the multiplication.
if (double.IsNaN(value) || double.IsInfinite(value)) return double.NaN;
// Only the two canonical bases are valid; anything else is a caller bug.
if (dataBase is not (1000 or 1024)) return double.NaN;
// Unknown unit symbols miss the table (null) — treat as invalid.
int? fromExp = ExponentOf(fromUnit);
int? toExp = ExponentOf(toUnit);
if (fromExp is null || toExp is null) return double.NaN;
return value * Math.Pow(dataBase, fromExp.Value) / Math.Pow(dataBase, toExp.Value);
}
}
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 →