Epsitec.Bcx.Core 7.3.3.2636

Prefix Reserved
There is a newer version of this package available.
See the version list below for details.
dotnet add package Epsitec.Bcx.Core --version 7.3.3.2636
                    
NuGet\Install-Package Epsitec.Bcx.Core -Version 7.3.3.2636
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Epsitec.Bcx.Core" Version="7.3.3.2636" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Epsitec.Bcx.Core" Version="7.3.3.2636" />
                    
Directory.Packages.props
<PackageReference Include="Epsitec.Bcx.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Epsitec.Bcx.Core --version 7.3.3.2636
                    
#r "nuget: Epsitec.Bcx.Core, 7.3.3.2636"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Epsitec.Bcx.Core@7.3.3.2636
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Epsitec.Bcx.Core&version=7.3.3.2636
                    
Install as a Cake Addin
#tool nuget:?package=Epsitec.Bcx.Core&version=7.3.3.2636
                    
Install as a Cake Tool

Bcx.Core

Base Class Library Extensions (Core Library)

NuGet License: MIT

Overview

Bcx.Core is a comprehensive .NET Standard 2.0 library that provides powerful extensions and utilities for the Base Class Library (BCL). It offers a rich set of functionality including functional programming patterns, reactive extensions, advanced collection types, I/O utilities, console enhancements, and much more.

Copyright ยฉ 2013-2025, EPSITEC SA, CH-1400 Yverdon-les-Bains, Switzerland
Author & Maintainer: Roger VUISTINER

Installation

Install via NuGet Package Manager:

Install-Package Epsitec.Bcx.Core

Or via .NET CLI:

dotnet add package Epsitec.Bcx.Core

Target Framework

  • .NET Standard 2.0 - Compatible with .NET Framework 4.6.1+, .NET Core 2.0+, .NET 5+, and later versions

Quick Start

using Bcx;
using Bcx.Collections;
using Bcx.Threading;

// Use Option monad for safe null handling
Option<User> user = GetUser(id);
var userName = user.Match(
    some: u => u.Name,
    none: () => "Unknown"
);

// Repository with automatic reference counting
var repo = new Repository<string, DbConnection>();
using (var conn = repo.GetOrAdd("main", _ => new SqlConnection(connStr)))
{
    // Use connection - automatically managed
}

// Enhanced console with colors
using (ConsoleEx.InitializeInvariant())
{
    var success = new ColoredText("โœ“ Done", EscapeSequence.Green);
    Console.WriteLine(success);
}

// Task with timeout
await LongRunningTask().Timeout(TimeSpan.FromSeconds(30));

// Parse and use ranges
var range = Range.Parse("1.0..2.0");
var inRange = range.Contains("1.5"); // true

Table of Contents

Key Features

๐ŸŽฏ Functional Programming

  • Function Composition: After, Then methods for composing functions
  • Currying & Uncurrying: Transform functions between curried and uncurried forms
  • Partial Application: Apply arguments incrementally
  • Memoization: Cache function results with MemoizeCache
  • Option Monad: Robust optional value handling (inspired by language-ext)
// Option monad example
Option<int> GetValue() => Option.Some(42);
Option<int> noValue = Option.None;

๐Ÿ“ฆ Advanced Collections

  • Repository<TKey, TValue>: Thread-safe, reference-counted resource management with deterministic disposal
  • MultiValueDictionary: Dictionary that maps keys to multiple values
  • IndexedHashSet: Hash set with index-based access
  • LookupHashSetTable & LookupListTable: Efficient lookup tables
  • WeakReferenceDictionary: Dictionary with weak references for memory management
  • ReferenceEqualityComparer: Compare objects by reference equality
  • AnonymousComparer & AnonymousEqualityComparer: Create comparers from lambda expressions

๐Ÿ“ Range System

Comprehensive range support with a flexible grammar:

Range.Parse("1")         // Degenerated: single value
Range.Parse("..3")       // Right-bounded: before 3
Range.Parse("1..")       // Left-bounded: since 1
Range.Parse("1..3")      // Bounded: since 1 but before 3
Range.Parse("")          // Infinity: for all
Range.Parse("1..3,6,8..") // Set: multiple ranges

๐Ÿงต Threading & Async

  • Task Extensions: Timeout, LINQ-style operators (Select, SelectMany, Where)
  • ValueTask Extensions: Enhanced ValueTask support
  • SessionMutex: Named mutex for cross-process synchronization
  • Singleton<T>: Thread-safe singleton pattern implementation
  • ReaderWriterLock Extensions: Simplified lock management
await task.Timeout(TimeSpan.FromSeconds(30));

๐Ÿ–ฅ๏ธ Console Enhancement

  • VT100 Support: ANSI escape sequence handling
  • ColoredText: Rich colored text with automatic escape sequence management
  • TextSpan: Advanced text layout with padding, tabs, and width calculations
  • Terminal: Cross-platform terminal utilities
  • ConsoleEx: Enhanced console initialization with culture and encoding support
using (ConsoleEx.InitializeInvariant())
{
    // Console configured with invariant culture and proper encoding
}

๐Ÿ“‚ I/O Utilities

  • PathEx: Extended path manipulation (sanitization, wildcards, URI creation)
  • FileEx & DirectoryEx: Enhanced file and directory operations
  • ConcurrentFile: Thread-safe file operations
  • StreamExtensions: Stream reading and manipulation utilities
  • DirectoryFinder: Recursive directory traversal
  • PathSpec: Path specification and matching

๐Ÿ” Security

  • FileHash: SHA256 file hashing utilities
  • ICertificateProvider: Certificate management interface
  • ISecure: Security contract interface
  • SignatureException & EncryptionException: Security-related exceptions

๐Ÿ”„ Type Conversion

  • TypeConverter<T1, T2>: Bidirectional type conversion facade
  • EnumConverter: Convert between enums by name, map, or cast
  • IEnumConverter: Extensible enum conversion interface
TypeConverters.Register<Celsius, Fahrenheit>(
    c => new Fahrenheit(c.Value * 9/5 + 32),
    f => new Celsius((f.Value - 32) * 5/9)
);
var fahrenheit = TypeConverter<Celsius, Fahrenheit>.Convert(celsius);

๐Ÿ” LINQ Extensions

  • Traverse: Non-recursive graph traversal
  • Chunk: Split sequences into chunks
  • Throw/Trace: Observable and enumerable debugging extensions

๐Ÿ“ String & Text

  • StringExtensions: HasValue, HasContent, SplitPreservingDelimiters, and more
  • StringBuilder Extensions: Enhanced string building
  • SynonymsTable: Manage text synonyms and aliases
  • StringWriterWithEncoding: String writer with custom encoding

๐Ÿ”ข Math & Numerics

  • MathEx: Extended math operations including double-precision utilities
  • DecimalExtensions: Decimal number operations

๐Ÿ›ค๏ธ Error Handling

  • Bumpy<T>: Result type for railway-oriented programming that encapsulates either a successful value or an exception, providing type-safe error handling without throwing exceptions immediately

โฑ๏ธ Time Management

  • ITimeService: Abstraction for time operations (testable time)
  • DualTime: Work with multiple time representations
  • TimeSpan Extensions: Enhanced timespan operations

๐ŸŽจ Enums

  • EnumEx: GetValues<T>, GetFlags<T>, GetDescription from attributes
  • IEnumConverter: Convert between enum types

๐Ÿงฉ System Extensions

  • DateTimeExtensions & DateTimeOffsetExtensions: Date/time manipulation
  • DisposableExtensions: Reference counting for IDisposable (AddRef)
  • ExceptionExtensions: Enhanced exception handling
  • ObjectExtensions: Common object utilities
  • TypeExtensions: Type introspection and manipulation
  • UriExtensions: URI utilities
  • VersionExtensions: Version comparison and parsing

๐Ÿ“‹ Command Line

  • CommandLineSplitter: Parse command-line arguments

๐ŸŽฏ Filters

  • Predicate & PredicateFilter: Functional filtering
  • RegexFilter: Regular expression-based filtering

๐Ÿงฐ Diagnostics

  • TraceMT: Multi-threaded tracing
  • ObservableExtensions: Throw and trace for observables
  • LinqExtensions: Throw and trace for LINQ queries

๐Ÿ“ฆ Resources

  • ResourceLoader: Load embedded resources

Additional Features

๐ŸŽฏ System Extensions

DisposableExtensions - Reference counting for IDisposable:

var resource = new MyDisposable();
resource.AddRef();  // Increment reference count
// ... use resource ...
resource.Release(); // Decrement and dispose when zero

TypeExtensions - Type introspection:

var isNullable = typeof(int?).IsNullable();
var underlyingType = typeof(int?).GetNullableUnderlyingType();
bool implements = typeof(MyClass).Implements<IDisposable>();

ExceptionExtensions - Enhanced exception handling:

try
{
    RiskyOperation();
}
catch (Exception ex)
{
    var innerMost = ex.GetInnermostException();
    var allMessages = ex.GetAllMessages();
    Log(allMessages);
}
๐Ÿ“Š Console Tables

Batch Mode - Build complete tables:

var table = new TableBuilder()
    .SetWidth(80)
    .UsePreset(() => TableStyle.Presets.Modern)
    .AddColumn("Name", 20)
    .AddColumn("Status", 15)
    .AddRow("Task 1", "Complete")
    .AddRow("Task 2", "Pending")
    .Build();

Console.WriteLine(table.Render());

Streaming Mode - Dynamic row rendering:

var renderer = new TableRenderer()
    .SetWidth(100)
    .UsePreset(() => TableStyle.Presets.Box)
    .AddColumn("Time", 12)
    .AddColumn("Event", 60);

renderer.RenderHeader(Console.Out);

foreach (var evt in GetEvents())
{
    renderer.RenderRow(Console.Out, evt.Time, evt.Description);
}

renderer.RenderFooter(Console.Out);

Table Style Presets:

  • TableStyle.Presets.Default - Simple ASCII borders
  • TableStyle.Presets.Modern - Clean Unicode borders
  • TableStyle.Presets.Box - Box drawing characters
  • TableStyle.Presets.Minimal - Minimal borders
  • TableStyle.Presets.None - No borders
๐Ÿ”„ Filters

PredicateFilter - Combine multiple predicates:

var filter = new PredicateFilter<int>()
    .Add(x => x > 0)
    .Add(x => x % 2 == 0);

var filtered = numbers.Where(filter.Matches);

RegexFilter - Regular expression filtering:

var filter = new RegexFilter(@"^\d{3}-\d{4}$");
var phoneNumbers = items.Where(filter.IsMatch);
๐Ÿ“ฆ Resources

ResourceLoader - Load embedded resources:

// Load string resource
var json = ResourceLoader.LoadString(
    assembly, 
    "MyApp.Resources.config.json"
);

// Load binary resource
var bytes = ResourceLoader.LoadBytes(
    assembly, 
    "MyApp.Resources.icon.png"
);
๐Ÿ”ข Random Extensions
var random = new Random();

// Generate random boolean
bool coinFlip = random.NextBool();

// Random element from collection
var item = collection.RandomElement(random);

// Shuffle collection
var shuffled = items.Shuffle(random);
๐Ÿงฉ Entity and Identity
// Entity with identity
public class User : Entity<int>
{
    public User(int id) : base(id) { }
    public string Name { get; set; }
}

// Entities with same ID are equal
var user1 = new User(1) { Name = "Alice" };
var user2 = new User(1) { Name = "Bob" };
bool areEqual = user1.Equals(user2); // true

Dependencies

This library leverages high-quality NuGet packages:

  • Microsoft.CSharp (Latest) - Dynamic language runtime support and dynamic type features
  • System.Collections.Immutable (Latest) - Immutable collection types for thread-safe operations
  • System.Interactive (Latest) - Interactive LINQ extensions (Ix)
  • System.IO.Pipelines (Latest) - High-performance I/O primitives for efficient data streaming
  • System.Reactive (Latest) - Reactive Extensions (Rx) for composing asynchronous and event-based programs
  • System.Text.Json (Latest) - High-performance JSON serialization and deserialization

All dependencies target .NET Standard 2.0 for maximum compatibility across .NET implementations.

Comprehensive Code Examples

๐ŸŽฏ Option Monad - Complete Examples

using Bcx;

// Creating optional values
Option<int> some = Option.Some(42);
Option<int> none = Option.None<int>();
Option<string> empty = Option.none; // Using the static instance

// Implicit conversions
Option<string> fromValue = "Hello";
Option<int> fromNone = Option.none;

// Safe navigation with Map
Option<string> userName = GetUser(userId)
    .Map(user => user.Name)
    .Map(name => name.ToUpper());

// Pattern matching
var message = FindUser(42).Match(
    some: user => $"Found: {user.Name}",
    none: () => "User not found"
);

// LINQ query syntax with SelectMany
var result = from user in GetUser(userId)
             from address in GetAddress(user.Id)
             select $"{user.Name} lives at {address.Street}";

// Combining multiple options
var combined = Option.Some(10)
    .Bind(x => Option.Some(x * 2))
    .Bind(x => x > 15 ? Option.Some(x) : Option.None<int>());

// Extract value safely
if (option.IsSome)
{
    var value = option.GetValue();
    Console.WriteLine(value);
}

// Convert to nullable
int? nullable = option.ToNullable();

// Execute action only if some
option.IfSome(value => Console.WriteLine($"Value: {value}"));

public Option<User> GetUser(int id)
{
    var user = database.Users.FirstOrDefault(u => u.Id == id);
    return Option.Optional(user);
}

๐Ÿ›ค๏ธ Bumpy<T> - Railway-Oriented Programming

using Bcx;

// Create results
var success = new Bumpy<int>(42);
var failure = new Bumpy<int>(new InvalidOperationException("Failed"));

// Using factory method (type inferred)
var result = Bumpy.Create("Hello");

// Real-world example: safe division
public Bumpy<decimal> CalculateRatio(decimal numerator, decimal denominator)
{
    try
    {
        if (denominator == 0)
            return new Bumpy<decimal>(new DivideByZeroException("Cannot divide by zero"));
        
        return new Bumpy<decimal>(numerator / denominator);
    }
    catch (Exception ex)
    {
        return new Bumpy<decimal>(ex);
    }
}

// Using Bumpy results
var ratio = CalculateRatio(100, 5);
if (ratio.Succeeded)
{
    Console.WriteLine($"Ratio: {ratio.Value:F2}");
}
else
{
    Console.WriteLine($"Error: {ratio.Exception.Message}");
    LogError(ratio.Exception);
}

// Chaining operations
public Bumpy<Order> ProcessOrder(OrderRequest request)
{
    var validation = ValidateOrder(request);
    if (validation.Failed) return new Bumpy<Order>(validation.Exception);
    
    var order = CreateOrder(validation.Value);
    if (order.Failed) return order;
    
    var saved = SaveOrder(order.Value);
    return saved;
}

๐Ÿ“ฆ Repository Pattern with Reference Counting

using Bcx.Collections;

// Create repository for managing database connections
var repository = new Repository<string, DatabaseConnection>();

// Get or add connection (ref count incremented automatically)
var conn1 = repository.GetOrAdd("main", key => new DatabaseConnection($"Server={key}"));
var conn2 = repository.GetOrAdd("main", key => new DatabaseConnection($"Server={key}")); // Returns same instance

// Multiple references to same connection
Console.WriteLine($"RefCount: {repository.Count}"); // Still 1 unique connection

// Release when done (ref count decremented)
repository.Release("main"); // RefCount now 1
repository.Release("main"); // RefCount now 0, connection disposed

// Working with multiple resources
var dbRepo = new Repository<string, DatabaseConnection>();

using (var conn = dbRepo.GetOrAdd("main", _ => new DatabaseConnection("main")))
{
    // Use connection
    var data = conn.Query("SELECT * FROM Users");
    
    // Automatically released when exiting using block
}

// Subscribe to repository changes
repository.Subscribe(kv => Console.WriteLine($"Changed: {kv.Key}"));

// Check if resource exists
if (repository.Contains("main"))
{
    Console.WriteLine("Main connection exists");
}

๐Ÿ“ Ranges - Comprehensive Range System

using Bcx;

// Parse different range formats
var single      = Range.Parse("5");           // Single value: 5
var leftBound   = Range.Parse("10..");        // From 10 onwards
var rightBound  = Range.Parse("..20");        // Up to (but not including) 20
var bounded     = Range.Parse("10..20");      // From 10 to 20 (exclusive end)
var infinity    = Range.Parse("");            // All values
var set         = Range.Parse("1..5,10,15..20"); // Multiple ranges

// Using ranges for filtering
var versions = new[] { "1.0", "2.0", "2.5", "3.0", "4.0" };
var versionRange = Range.Parse("2.0..4.0");

// Check if value is in range
bool isInRange = versionRange.Contains("2.5");

// Filter collections
var filteredVersions = versions.Where(v => versionRange.Contains(v));

// Version filtering example
public bool IsCompatibleVersion(string version, string rangeSpec)
{
    var range = Range.Parse(rangeSpec);
    return range.Contains(version);
}

// Usage
var isCompatible = IsCompatibleVersion("2.5.1", "2.0..3.0"); // true

๐Ÿ–ฅ๏ธ Console Enhancement with Tables and Colors

using Bcx;

// Initialize console with proper encoding and VT100 support
using (ConsoleEx.InitializeInvariant())
{
    // Colored text
    var success = new ColoredText("โœ“ Success", EscapeSequence.Green);
    var error = new ColoredText("โœ— Error", EscapeSequence.Red);
    var warning = new ColoredText("โš  Warning", EscapeSequence.Yellow);
    
    Console.WriteLine(success.PadRight(50));
    Console.WriteLine(error.PadRight(50));
    Console.WriteLine(warning.PadRight(50));
    
    // Shrink long text with ellipsis
    var longText = new ColoredText("This is a very long text", EscapeSequence.Cyan);
    Console.WriteLine(longText.Shrink(10)); // "This is aโ€ฆ"
    
    // Create beautiful console tables
    var table = new TableBuilder()
        .SetWidth(80)
        .UsePreset(() => TableStyle.Presets.Modern)
        .AddColumn("Name", 20)
        .AddColumn("Age", 10)
        .AddColumn("Email", 30)
        .AddRow("Alice", "30", "alice@example.com")
        .AddRow("Bob", "25", "bob@example.com")
        .AddRow("Charlie", "35", "charlie@example.com")
        .Build();
    
    Console.WriteLine(table.Render());
    
    // Dynamic table building with elastic columns
    var dynamicTable = new TableBuilder()
        .SetWidth(100)
        .SetBorderStyle(BorderStyle.Double)
        .AddColumn("ID", 5, fixed: true)
        .AddColumn("Description", 0, fixed: false) // Elastic column
        .AddColumn("Status", 15, fixed: true)
        .AddRow("1", "Process data from source", "โœ“ Complete")
        .AddRow("2", "Validate and transform records", "โณ Running")
        .AddRow("3", "Export results to destination", "โธ Pending")
        .Build();
    
    Console.WriteLine(dynamicTable.Render());
    
    // Stream rows dynamically
    var renderer = new TableRenderer()
        .SetWidth(80)
        .UsePreset(() => TableStyle.Presets.Minimal)
        .AddColumn("Time", 10)
        .AddColumn("Message", 60);
    
    renderer.RenderHeader(Console.Out);
    
    foreach (var logEntry in GetLogEntries())
    {
        renderer.RenderRow(Console.Out, logEntry.Time, logEntry.Message);
    }
    
    renderer.RenderFooter(Console.Out);
}

// Advanced VT100 usage
VT100.Enable();
Console.WriteLine($"{EscapeSequence.Bold}{EscapeSequence.Green}Bold Green Text{EscapeSequence.Reset}");
Console.WriteLine($"{EscapeSequence.Underline}Underlined{EscapeSequence.Reset}");

๐Ÿงต Threading - Task Extensions and LINQ

using Bcx.Threading;
using System.Threading.Tasks;

// Task timeout
try
{
    await LongRunningOperation().Timeout(TimeSpan.FromSeconds(30));
}
catch (TimeoutException)
{
    Console.WriteLine("Operation timed out");
}

// LINQ-style task composition
var result = await GetUserId()
    .Select(id => GetUser(id))
    .Select(user => user.Name);

// Async LINQ query syntax
var userName = await (
    from id in Task.FromResult(42)
    from user in GetUserAsync(id)
    from dept in GetDepartmentAsync(user.DepartmentId)
    select $"{user.Name} ({dept.Name})"
);

// Where clause with tasks
var validUsers = await GetUserAsync(userId)
    .Where(user => user.Age >= 18);

// Singleton pattern (thread-safe)
var config = Singleton<Configuration>.Instance;

// Cross-process synchronization with SessionMutex
using (var mutex = new SessionMutex("MyApp_SingleInstance"))
{
    if (mutex.WaitOne(TimeSpan.FromSeconds(5)))
    {
        try
        {
            // Only one instance can enter this block
            RunApplication();
        }
        finally
        {
            mutex.ReleaseMutex();
        }
    }
    else
    {
        Console.WriteLine("Another instance is already running");
    }
}

// ReaderWriterLock extensions
using (readerWriterLock.ReadLock())
{
    // Multiple readers allowed
    var data = ReadData();
}

using (readerWriterLock.WriteLock())
{
    // Exclusive write access
    WriteData(newData);
}

๐Ÿ” LINQ Extensions - Traverse and More

using Bcx.Linq;

// Traverse hierarchies without recursion
public class TreeNode
{
    public string Name { get; set; }
    public List<TreeNode> Children { get; set; } = new();
}

var root = BuildTree();

// Get all nodes in the tree
var allNodes = root.Traverse(node => node.Children);

// Find all files in directory tree
var rootDir = new DirectoryInfo(@"C:\Projects");
var allFiles = rootDir.Traverse(
    dir => dir.GetDirectories(),
    traversalPredicate: dir => !dir.Name.StartsWith(".")
).SelectMany(dir => dir.GetFiles());

// Traverse with conditions
var publicNodes = root.Traverse(
    node => node.Children,
    traversalPredicate: node => node.IsPublic,
    ignorePredicate: node => node.IsHidden
);

// Chunk sequences for batch processing
var items = Enumerable.Range(1, 100);
var batches = items.Chunk(10);

foreach (var batch in batches)
{
    await ProcessBatchAsync(batch);
}

// Trace LINQ queries for debugging
var result = items
    .Where(x => x > 10)
    .Trace("After filter")
    .Select(x => x * 2)
    .Trace("After select")
    .ToList();

๐Ÿ”„ Type Conversion System

using Bcx;
using Bcx.Converters;

// Register bidirectional converter
TypeConverters.Register<Celsius, Fahrenheit>(
    c => new Fahrenheit(c.Value * 9 / 5 + 32),
    f => new Celsius((f.Value - 32) * 5 / 9)
);

// Use converter
var celsius = new Celsius(100);
var fahrenheit = TypeConverter<Celsius, Fahrenheit>.Convert(celsius);
var backToCelsius = TypeConverter<Fahrenheit, Celsius>.Convert(fahrenheit);

// Enum conversion by name
public enum SourceStatus { Active, Inactive, Pending }
public enum TargetStatus { Active, Inactive, Pending, Archived }

var source = SourceStatus.Active;
var target = EnumConverter.ConvertByName<SourceStatus, TargetStatus>(source);

// Enum conversion with mapping
var mapping = new Dictionary<SourceStatus, TargetStatus>
{
    [SourceStatus.Active] = TargetStatus.Active,
    [SourceStatus.Inactive] = TargetStatus.Archived,
    [SourceStatus.Pending] = TargetStatus.Pending
};

var converted = EnumConverter.ConvertByMap(source, mapping);

// Get all enum values
var allStatuses = EnumEx.GetValues<SourceStatus>();

// Get enum flags
var flags = EnumEx.GetFlags<FileAttributes>();

๐Ÿ“‚ IO Utilities - Path and File Operations

using Bcx.IO;

// Sanitize file names
var fileName = "My<File>Name?.txt";
var safe = PathEx.GetSanitizedFileName(fileName); // "My_File_Name_.txt"

// Safe file name extraction
var fullPath = @"C:\Projects\MyApp\file.txt";
var name = PathEx.GetFileNameSafe(fullPath); // "file.txt"

// Create URI from path
var uri = PathEx.CreateUriFromPath(@"C:\Projects\MyApp");

// Get full path with custom base directory
var relativePath = "../data/config.json";
var baseDir = @"C:\Projects\MyApp\bin";
var fullPath2 = PathEx.GetFullPath(relativePath, baseDir);

// Concurrent file operations (thread-safe)
await ConcurrentFile.WriteAllTextAsync("log.txt", "Log entry\n");
var content = await ConcurrentFile.ReadAllTextAsync("log.txt");

// Directory traversal
var finder = new DirectoryFinder(@"C:\Projects");
var allDirs = finder.GetDirectories("*", recursive: true);

// File hash computation
var hash = FileHash.ComputeSha256(@"C:\path\to\file.exe");
var isValid = FileHash.VerifySha256(filePath, expectedHash);

// Stream extensions
using var stream = File.OpenRead("data.bin");
var bytes = stream.ReadAllBytes();
var text = stream.ReadAllText(Encoding.UTF8);

๐ŸŽจ Functional Programming Patterns

using Bcx.Functional;

// Function composition
Func<int, int> addTwo = x => x + 2;
Func<int, int> multiplyThree = x => x * 3;
Func<int, int> square = x => x * x;

// Chain functions: (5 + 2) * 3 = 21
var composed = addTwo.Then(multiplyThree);
var result1 = composed(5);

// Or use After: multiplyThree after addTwo
var composed2 = multiplyThree.After(addTwo);
var result2 = composed2(5);

// Complex composition
var pipeline = addTwo
    .Then(multiplyThree)
    .Then(square);
var result3 = pipeline(5); // ((5 + 2) * 3)ยฒ = 441

// Currying - transform multi-parameter function to chain of single-parameter functions
Func<int, int, int> add = (x, y) => x + y;
var curriedAdd = add.Curry();
var add5 = curriedAdd(5);
var result4 = add5(10); // 15

// Partial application
Func<int, int, int, int> sum3 = (a, b, c) => a + b + c;
var sum10AndPartial = sum3.PartialApply(10); // Fix first parameter
var result5 = sum10AndPartial(20, 30); // 10 + 20 + 30 = 60

// Memoization (cache function results)
Func<int, int> expensiveCalculation = x =>
{
    Thread.Sleep(1000); // Simulate expensive operation
    return x * x;
};

// Results are cached
var memoized = expensiveCalculation.Memoize();
var r1 = memoized(5); // Takes 1 second
var r2 = memoized(5); // Instant (cached)
var r3 = memoized(10); // Takes 1 second

๐Ÿ“ String and Text Processing

using Bcx;
using Bcx.Text;

// String extensions
string text = "  Hello  ";
bool hasValue = text.HasValue();      // true (not null or empty)
bool hasContent = text.HasContent();  // true (not null, empty, or whitespace)

string? nullText = null;
bool hasValue2 = nullText.HasValue(); // false

// Split preserving delimiters
var input = "a,b;c,d";
var parts = input.SplitPreservingDelimiters(new[] { ',', ';' });
// Result: ["a", ",", "b", ";", "c", ",", "d"]

// Synonyms table for text normalization
var synonyms = new SynonymsTable();
synonyms.Add("color", "colour", "Color", "Colour");
synonyms.Add("center", "centre", "Center", "Centre");

var normalized1 = synonyms.Normalize("colour"); // "color"
var normalized2 = synonyms.Normalize("centre"); // "center"

// Check if text is synonym
bool isSynonym = synonyms.IsSynonym("colour", "color"); // true

// Global synonyms tables
SynonymsTables.Default.Add("gray", "grey");

// StringBuilder extensions
var sb = new StringBuilder();
sb.AppendLineInvariant($"Value: {42}");
sb.AppendFormatInvariant("Total: {0:F2}", 123.45);

// String writer with custom encoding
using var writer = new StringWriterWithEncoding(Encoding.UTF8);
writer.WriteLine("UTF-8 content");
var content = writer.ToString();

๐Ÿ” Security - File Hashing and Certificates

using Bcx.Security;

// Compute SHA256 hash of file
var filePath = @"C:\Downloads\installer.exe";
var hash = FileHash.ComputeSha256(filePath);
Console.WriteLine($"SHA256: {hash}");

// Verify file integrity
var expectedHash = "ABC123...";
bool isValid = FileHash.VerifySha256(filePath, expectedHash);

if (isValid)
{
    Console.WriteLine("File integrity verified");
}
else
{
    throw new SignatureException("File has been tampered with");
}

// Certificate provider interface
public class MyCertificateProvider : ICertificateProvider
{
    public X509Certificate2 GetCertificate(string name)
    {
        // Load certificate from store or file
        return LoadCertificate(name);
    }
}

// Use in secure operations
public class SecureService : ISecure
{
    public bool IsSecure => true;
    
    public void SecureOperation()
    {
        // Implement secure logic
    }
}

๐Ÿ“‹ Command Line Parsing

using Bcx.CommandLine;

// Parse command line with quoted arguments
var commandLine = "--config \"C:\\My Documents\\app.config\" --verbose --port 8080";
var args = CommandLineSplitter.Split(commandLine);

// Result: ["--config", "C:\\My Documents\\app.config", "--verbose", "--port", "8080"]

// Handle complex escaping
var complex = "app.exe \"arg with spaces\" 'single quotes' --flag=value";
var parsed = CommandLineSplitter.Split(complex);

// Build command lines
var builder = new StringBuilder();
builder.Append("dotnet");
builder.Append(" run");
builder.Append(" --project \"My Project.csproj\"");
var command = builder.ToString();

๐Ÿ”ข Math Extensions

using Bcx;
using Bcx.System;

// Double precision utilities
double value = 1.23456789;
var rounded = MathEx.Round(value, 2); // 1.23

// Check if doubles are approximately equal
bool areEqual = MathEx.AreEqual(1.0000001, 1.0000002, tolerance: 0.001);

// Decimal extensions
decimal amount = 123.456m;
var rounded2 = amount.Round(2); // 123.46
var truncated = amount.Truncate(2); // 123.45

// Clamp values
int clamped = 150.Clamp(0, 100); // 100

// Integer extensions
int number = 42;
bool isEven = number.IsEven();
bool isOdd = number.IsOdd();

โฑ๏ธ Time Management

using Bcx.Time;

// Testable time service
public class MyService
{
    private readonly ITimeService timeService;
    
    public MyService(ITimeService timeService)
    {
        this.timeService = timeService;
    }
    
    public void LogAction()
    {
        var now = timeService.Now;
        Console.WriteLine($"Action at: {now}");
    }
}

// In production
var service = new MyService(new SystemTimeService());

// In tests
var mockTime = new MockTimeService(new DateTime(2025, 1, 1));
var testService = new MyService(mockTime);

// DualTime for multiple time representations
var dualTime = new DualTime(DateTime.UtcNow, DateTimeOffset.Now);

// TimeSpan extensions
var duration = TimeSpan.FromMinutes(90);
var formatted = duration.ToHumanReadable(); // "1 hour 30 minutes"

๐Ÿ” Diagnostics and Debugging

using Bcx.Diagnostics;

// Multi-threaded tracing
TraceMT.WriteLine("Application started");
TraceMT.WriteLineIf(debugMode, "Debug info");

// Trace LINQ operations
var items = Enumerable.Range(1, 100)
    .Where(x => x % 2 == 0)
    .Trace("After filter")
    .Select(x => x * x)
    .Trace("After select")
    .ToList();

// Trace observables
var observable = Observable.Range(1, 10)
    .Where(x => x > 5)
    .Trace("Filtered values")
    .Select(x => x * 2);

// Throw exceptions in pipelines
var result = items
    .Where(x => x > 0)
    .Throw<InvalidOperationException>(x => x < 0, "Negative value found")
    .ToList();

Building and Packaging

Creating a NuGet Package

To create a NuGet package, use the provided batch script:

zou-nuget.bat

This script automates the complete packaging workflow:

  1. Build the project with Pack=true MSBuild property
  2. Create the NuGet package (.nupkg) in ..\.nupkg directory
  3. Create the symbol package (.snupkg) with embedded sources
  4. Sign the package (if signing is configured)
  5. Push to nuget.org (if credentials are configured)

Manual Build

Alternatively, build manually with MSBuild:

dotnet build -c Release /p:Pack=true

Or using MSBuild directly:

msbuild Bcx.Core.csproj /p:Configuration=Release /p:Pack=true

Package Configuration

When building with Pack=true, the following features are enabled:

Package Metadata:

  • PackageId: Epsitec.Bcx.Core
  • Title: Base Class Library Extensions (Core Library)
  • License: MIT License Expression
  • Icon: Bcx.Icon.png (embedded)
  • README: README.md (this file, embedded)

Debug Experience:

  • Embedded sources - All source files embedded in .snupkg for step-through debugging
  • Portable PDB - Debug symbols in portable format for cross-platform debugging
  • Source Link - Links to source repository for online source viewing

Build Quality:

  • Deterministic builds - Reproducible builds with same input = same output (CI/CD friendly)
  • Compiler-generated files - Output to obj\Generated for inspection
  • Continuous Integration - Optimized for automated build environments

Package Contents

The NuGet package includes:

  • โœ… Compiled library (Bcx.Core.dll)
  • โœ… XML documentation (Bcx.Core.xml)
  • โœ… Package icon
  • โœ… README file
  • โœ… Symbol package (.snupkg) with embedded sources

Project Structure

Bcx.Core/
โ”œโ”€โ”€ Adornment/          # Text coloring and formatting
โ”‚   โ”œโ”€โ”€ ColoredText.cs          # Rich colored text with ANSI escape sequences
โ”‚   โ””โ”€โ”€ ShrinkHelpers.cs        # Text shrinking utilities
โ”‚
โ”œโ”€โ”€ Collections/        # Advanced collection types
โ”‚   โ”œโ”€โ”€ Repository.cs           # Thread-safe reference-counted resource management
โ”‚   โ”œโ”€โ”€ MultiValueDictionary.cs # Dictionary mapping keys to multiple values
โ”‚   โ”œโ”€โ”€ IndexedHashSet.cs       # Hash set with index-based access
โ”‚   โ”œโ”€โ”€ LookupHashSetTable.cs   # Efficient hash set lookup table
โ”‚   โ”œโ”€โ”€ LookupListTable.cs      # Efficient list lookup table
โ”‚   โ”œโ”€โ”€ WeakReferenceDictionary.cs # Dictionary with weak references
โ”‚   โ”œโ”€โ”€ AnonymousComparer.cs    # Create comparers from lambdas
โ”‚   โ””โ”€โ”€ AnonymousEqualityComparer.cs # Create equality comparers from lambdas
โ”‚
โ”œโ”€โ”€ CommandLine/        # Command-line parsing
โ”‚   โ””โ”€โ”€ CommandLineSplitter.cs  # Parse command-line arguments
โ”‚
โ”œโ”€โ”€ Console/            # Console enhancements and VT100
โ”‚   โ”œโ”€โ”€ ConsoleEx.cs            # Enhanced console initialization
โ”‚   โ”œโ”€โ”€ VT100.cs                # ANSI escape sequence support
โ”‚   โ”œโ”€โ”€ EscapeSequence.cs       # Predefined color/formatting codes
โ”‚   โ”œโ”€โ”€ Terminal.cs             # Cross-platform terminal utilities
โ”‚   โ”œโ”€โ”€ Tables/                 # Console table rendering
โ”‚   โ”‚   โ”œโ”€โ”€ TableBuilder.cs     # Fluent API for building tables
โ”‚   โ”‚   โ”œโ”€โ”€ TableRenderer.cs    # Dynamic row streaming
โ”‚   โ”‚   โ”œโ”€โ”€ TableStyle.cs       # Table styling and presets
โ”‚   โ”‚   โ””โ”€โ”€ Table.cs            # Complete rendered table
โ”‚   โ””โ”€โ”€ Formatting/             # Text layout and formatting
โ”‚       โ”œโ”€โ”€ TextSpan.cs         # Advanced text layout with width calculations
โ”‚       โ”œโ”€โ”€ TextSegment.cs      # Text segment representation
โ”‚       โ””โ”€โ”€ TextAlignment.cs    # Text alignment options
โ”‚
โ”œโ”€โ”€ Converters/         # Type conversion utilities
โ”‚   โ”œโ”€โ”€ TypeConverter.cs        # Bidirectional type conversion
โ”‚   โ”œโ”€โ”€ TypeConverters.cs       # Global converter registry
โ”‚   โ”œโ”€โ”€ EnumConverter.*.cs      # Enum conversion (ByName, ByMap, Cast)
โ”‚   โ””โ”€โ”€ ITypeConverter.cs       # Converter interface
โ”‚
โ”œโ”€โ”€ Diagnostics/        # Tracing and debugging
โ”‚   โ”œโ”€โ”€ TraceMT.cs              # Multi-threaded tracing
โ”‚   โ”œโ”€โ”€ LinqExtensions.Trace.cs # Trace LINQ queries
โ”‚   โ”œโ”€โ”€ LinqExtensions.Throw.cs # Throw in LINQ pipelines
โ”‚   โ””โ”€โ”€ ObservableExtensions.*.cs # Observable tracing/throwing
โ”‚
โ”œโ”€โ”€ Enums/              # Enum utilities
โ”‚   โ”œโ”€โ”€ EnumEx.cs               # GetValues, GetFlags, GetDescription
โ”‚   โ””โ”€โ”€ IEnumConverter.cs       # Enum conversion interface
โ”‚
โ”œโ”€โ”€ Exceptions/         # Custom exceptions
โ”‚   โ”œโ”€โ”€ ValueIsNoneException.cs
โ”‚   โ”œโ”€โ”€ ValueIsNullException.cs
โ”‚   โ”œโ”€โ”€ ResultIsNullException.cs
โ”‚   โ””โ”€โ”€ SomeNotInitalizedException.cs
โ”‚
โ”œโ”€โ”€ Filters/            # Filtering utilities
โ”‚   โ”œโ”€โ”€ Predicate.cs            # Functional predicates
โ”‚   โ”œโ”€โ”€ PredicateFilter.cs      # Predicate-based filtering
โ”‚   โ””โ”€โ”€ RegexFilter.cs          # Regex-based filtering
โ”‚
โ”œโ”€โ”€ Functional/         # Functional programming patterns
โ”‚   โ”œโ”€โ”€ FunctionExtensions.cs   # Composition, currying, partial application
โ”‚   โ””โ”€โ”€ MemoizeCache.cs         # Function result memoization
โ”‚
โ”œโ”€โ”€ IO/                 # File and directory utilities
โ”‚   โ”œโ”€โ”€ PathEx.cs               # Extended path manipulation
โ”‚   โ”œโ”€โ”€ FileEx.cs               # Enhanced file operations
โ”‚   โ”œโ”€โ”€ DirectoryEx.cs          # Enhanced directory operations
โ”‚   โ”œโ”€โ”€ ConcurrentFile.cs       # Thread-safe file operations
โ”‚   โ”œโ”€โ”€ StreamExtensions.cs     # Stream utilities
โ”‚   โ”œโ”€โ”€ DirectoryFinder.cs      # Recursive directory traversal
โ”‚   โ””โ”€โ”€ PathSpec.cs             # Path specification and matching
โ”‚
โ”œโ”€โ”€ Json/               # JSON serialization
โ”‚   โ””โ”€โ”€ SerializerOptions.cs    # JSON serializer configuration
โ”‚
โ”œโ”€โ”€ Linq/               # LINQ extensions
โ”‚   โ””โ”€โ”€ LinqExtensions.cs       # Traverse, Chunk, Closure
โ”‚
โ”œโ”€โ”€ Optional/           # Option monad
โ”‚   โ””โ”€โ”€ Option.cs               # Option<T>, Some<T>, None<T>, IOptional
โ”‚
โ”œโ”€โ”€ Ranges/             # Range system
โ”‚   โ”œโ”€โ”€ Range.cs                # Range parsing and factory methods
โ”‚   โ”œโ”€โ”€ IRange.cs               # Range interface
โ”‚   โ”œโ”€โ”€ Range.Bounded.cs        # Bounded range implementation
โ”‚   โ”œโ”€โ”€ Range.LeftBounded.cs    # Left-bounded range
โ”‚   โ”œโ”€โ”€ Range.RightBounded.cs   # Right-bounded range
โ”‚   โ”œโ”€โ”€ Range.Infinity.cs       # Infinite range
โ”‚   โ”œโ”€โ”€ Range.Degenerated.cs    # Single-value range
โ”‚   โ””โ”€โ”€ Range.Set.cs            # Multiple ranges
โ”‚
โ”œโ”€โ”€ Resources/          # Resource loading
โ”‚   โ””โ”€โ”€ ResourceLoader.cs       # Load embedded resources
โ”‚
โ”œโ”€โ”€ Security/           # Security and cryptography
โ”‚   โ”œโ”€โ”€ FileHash.cs             # SHA256 file hashing
โ”‚   โ”œโ”€โ”€ ICertificateProvider.cs # Certificate management interface
โ”‚   โ”œโ”€โ”€ ISecure.cs              # Security contract
โ”‚   โ”œโ”€โ”€ SignatureException.cs   # Signature-related exceptions
โ”‚   โ””โ”€โ”€ EncryptionException.cs  # Encryption-related exceptions
โ”‚
โ”œโ”€โ”€ System/             # Core BCL extensions
โ”‚   โ”œโ”€โ”€ Bumpy.cs                # Result type for railway-oriented programming
โ”‚   โ”œโ”€โ”€ DisposableExtensions.cs # Reference counting (AddRef, Release)
โ”‚   โ”œโ”€โ”€ StringExtensions.cs     # HasValue, HasContent, etc.
โ”‚   โ”œโ”€โ”€ DateTimeExtensions.cs   # Date/time manipulation
โ”‚   โ”œโ”€โ”€ TypeExtensions.cs       # Type introspection
โ”‚   โ”œโ”€โ”€ ExceptionExtensions.cs  # Exception handling utilities
โ”‚   โ”œโ”€โ”€ ObjectExtensions.cs     # Common object utilities
โ”‚   โ”œโ”€โ”€ MathEx.cs               # Extended math operations
โ”‚   โ”œโ”€โ”€ DecimalExtensions.cs    # Decimal operations
โ”‚   โ””โ”€โ”€ IntExtensions.cs        # Integer utilities
โ”‚
โ”œโ”€โ”€ Text/               # Text processing
โ”‚   โ”œโ”€โ”€ StringExtensions.cs     # String manipulation
โ”‚   โ”œโ”€โ”€ StringBuilder Extensions.cs # StringBuilder enhancements
โ”‚   โ”œโ”€โ”€ SynonymsTable.cs        # Text synonym management
โ”‚   โ”œโ”€โ”€ SynonymsTables.cs       # Global synonyms registry
โ”‚   โ””โ”€โ”€ StringWriterWithEncoding.cs # Custom encoding writer
โ”‚
โ”œโ”€โ”€ Threading/          # Threading and async utilities
โ”‚   โ”œโ”€โ”€ TaskExtensions.cs       # Task timeout, LINQ operators
โ”‚   โ”œโ”€โ”€ ValueTaskExtensions.cs  # ValueTask extensions
โ”‚   โ”œโ”€โ”€ SessionMutex.cs         # Cross-process mutex
โ”‚   โ”œโ”€โ”€ Singleton.cs            # Thread-safe singleton pattern
โ”‚   โ”œโ”€โ”€ ReaderWriterLockExtensions.cs # Lock management
โ”‚   โ””โ”€โ”€ FunctionExtensions.cs   # Async function utilities
โ”‚
โ””โ”€โ”€ Time/               # Time management
    โ”œโ”€โ”€ ITimeService.cs         # Testable time abstraction
    โ”œโ”€โ”€ DualTime.cs             # Multiple time representations
    โ””โ”€โ”€ TimeMismatchException.cs # Time-related exceptions

Real-World Usage Scenarios

Scenario 1: Building a CLI Application

using Bcx;
using System;

class Program
{
    static async Task Main(string[] args)
    {
        // Initialize console with proper encoding and colors
        using (ConsoleEx.InitializeInvariant())
        {
            // Parse command line
            var cmdArgs = CommandLineSplitter.Split(string.Join(" ", args));
            
            // Create beautiful output table
            var table = new TableBuilder()
                .SetWidth(ConsoleEx.Width)
                .UsePreset(() => TableStyle.Presets.Modern)
                .AddColumn("Task", 30)
                .AddColumn("Status", 15)
                .AddColumn("Time", 15);
            
            foreach (var task in GetTasks())
            {
                var status = task.IsComplete 
                    ? new ColoredText("โœ“ Complete", EscapeSequence.Green)
                    : new ColoredText("โณ Running", EscapeSequence.Yellow);
                
                table.AddRow(task.Name, status.ToString(), task.Duration);
            }
            
            Console.WriteLine(table.Build().Render());
        }
    }
}

Scenario 2: Safe Resource Management

using Bcx.Collections;

public class DatabaseManager
{
    private readonly Repository<string, DatabaseConnection> connections;
    
    public DatabaseManager()
    {
        connections = new Repository<string, DatabaseConnection>();
    }
    
    public async Task<TResult> ExecuteAsync<TResult>(
        string connectionName, 
        Func<DatabaseConnection, Task<TResult>> operation)
    {
        // Automatically manages reference counting
        var connection = connections.GetOrAdd(
            connectionName, 
            key => new DatabaseConnection(GetConnectionString(key))
        );
        
        try
        {
            return await operation(connection);
        }
        finally
        {
            connections.Release(connectionName);
        }
    }
}

Scenario 3: Error Handling with Railway-Oriented Programming

using Bcx;

public class OrderProcessor
{
    public Bumpy<Order> ProcessOrder(OrderRequest request)
    {
        // Validate
        var validation = ValidateRequest(request);
        if (validation.Failed) 
            return new Bumpy<Order>(validation.Exception);
        
        // Calculate
        var calculation = CalculatePricing(validation.Value);
        if (calculation.Failed) 
            return new Bumpy<Order>(calculation.Exception);
        
        // Save
        var order = SaveOrder(calculation.Value);
        return order;
    }
    
    private Bumpy<ValidatedRequest> ValidateRequest(OrderRequest request)
    {
        try
        {
            if (string.IsNullOrEmpty(request.CustomerId))
                throw new ValidationException("Customer ID required");
            
            return new Bumpy<ValidatedRequest>(new ValidatedRequest(request));
        }
        catch (Exception ex)
        {
            return new Bumpy<ValidatedRequest>(ex);
        }
    }
}

Scenario 4: Hierarchical Data Processing

using Bcx.Linq;

public class FileSystemAnalyzer
{
    public IEnumerable<FileInfo> FindAllFiles(string rootPath, string pattern)
    {
        var rootDir = new DirectoryInfo(rootPath);
        
        // Traverse directory tree without recursion
        return rootDir
            .Traverse(
                dir => dir.GetDirectories(),
                traversalPredicate: dir => !dir.Name.StartsWith("."),
                ignorePredicate: dir => dir.Name == "node_modules"
            )
            .SelectMany(dir => dir.GetFiles(pattern));
    }
    
    public long CalculateTotalSize(string rootPath)
    {
        return FindAllFiles(rootPath, "*.*")
            .Sum(file => file.Length);
    }
}

Code Quality

The library follows strict coding standards:

  • 2-space indentation for C# files (enforced by .editorconfig)
  • Comprehensive XML documentation for all public APIs
  • Copyright headers in all files: // Copyright ยฉ 2013-2025, EPSITEC SA, CH-1400 Yverdon-les-Bains, Switzerland
  • Thread-safe implementations where applicable (Repository, Singleton, etc.)
  • IDisposable patterns with proper cleanup and reference counting
  • Consistent naming following .NET conventions
  • Immutability where appropriate (records, readonly fields)

Performance Considerations

  • Repository<TKey, TValue>: Uses ConcurrentDictionary with Lazy<T> for thread-safe lazy initialization
  • Option<T>: Implemented as record types for structural equality and minimal overhead
  • Traverse: Non-recursive graph traversal avoids stack overflow with large hierarchies
  • Memoization: Thread-safe caching with ConcurrentDictionary
  • Task Extensions: Zero-allocation where possible using ValueTask
  • StringExtensions: Optimized for minimal allocations

License

This project is licensed under the MIT License.

Repository

Contributing

Contributions are welcome! Please ensure:

  • Code follows existing style and conventions (2-space indentation for C#)
  • All tests pass
  • XML documentation is provided for public APIs
  • Copyright headers are included: // Copyright ยฉ 2013-2025, EPSITEC SA, CH-1400 Yverdon-les-Bains, Switzerland
  • Code is thread-safe where appropriate
  • IDisposable resources are properly managed with reference counting patterns

Support

For issues, questions, or contributions, please visit the project repository at git.epsitec.ch.


Made with โค๏ธ by EPSITEC SA

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Epsitec.Bcx.Core:

Package Downloads
Epsitec.Passport.Shared

Passport.Shared - 3.46.4.2634 net10.0

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
7.4.5.2641 115 10/7/2026
7.3.3.2636 472 9/5/2026
7.3.2.2636 103 9/5/2026
7.3.1.2636 102 9/5/2026
7.3.0.2636 115 9/5/2026
7.1.5.2635 200 8/27/2026
7.1.3.2633 195 8/15/2026
6.9.2.2623 201 6/5/2026
5.8.7.2551 352 12/16/2025
5.8.6.2551 325 12/16/2025
5.1.0.2423 302 6/11/2024
5.0.0.2418 231 6/6/2024