Skip to content

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 →