ktsu.DelegateTransform 1.1.4

ktsu.DelegateTransform

A utility library for transforming values using delegates in C#.

License NuGet NuGet Downloads Build Status GitHub Stars

Introduction

DelegateTransform is a utility library that provides methods for transforming values using various delegate types in C#. It offers a clean and efficient way to apply transformations using ActionRef, Func, and FuncRef delegates, making your code more readable and functional.

Important: All With methods return a new transformed value - they never mutate the original input. This provides functional programming semantics even when using reference-based delegates.

Features

  • ActionRef Transformations: Modify copies of values by reference using action delegates
  • Func Transformations: Transform values using function delegates
  • FuncRef Transformations: Transform values by reference using function delegates that return values
  • Copy-on-Transform: Original values are never mutated
  • Generic Implementation: Works with any value or reference type

Supported Frameworks

  • .NET 10.0, 9.0, 8.0, 7.0, 6.0
  • .NET Standard 2.1

Installation

Package Manager Console

Install-Package ktsu.DelegateTransform

.NET CLI

dotnet add package ktsu.DelegateTransform

Package Reference

<PackageReference Include="ktsu.DelegateTransform" Version="x.y.z" />

Usage Examples

With ActionRef

The With method can be used with an ActionRef<T> delegate to apply a transformation by reference and return the result:

using ktsu.DelegateTransform;

int input = 5;
int result = DelegateTransform.With(input, (ref int x) => x *= 2);
// result is 10, input is still 5 (original unchanged)

With Func

The With method can be used with a Func<T, T> delegate to transform the input value:

using ktsu.DelegateTransform;

int input = 5;
int result = DelegateTransform.With(input, x => x * 2);
// result is 10

With FuncRef

The With method can be used with a FuncRef<T> delegate to transform the input value by reference:

using ktsu.DelegateTransform;

int input = 5;
int result = DelegateTransform.With(input, (ref int x) => x * x);
// result is 25, input is still 5 (original unchanged)

Chaining Transformations

You can chain multiple transformations by nesting calls:

using ktsu.DelegateTransform;

// Starting value
string input = "example";

// Chain of transformations
string step1 = DelegateTransform.With(input, s => s.ToUpper());           // "EXAMPLE"
string step2 = DelegateTransform.With(step1, s => s.Replace("EX", "**")); // "**AMPLE"
string result = DelegateTransform.With(step2, s => s + " transformed");   // "**AMPLE transformed"

Console.WriteLine(result); // Outputs: **AMPLE transformed

Complex Object Transformations

using ktsu.DelegateTransform;

var person = new Person { Name = "John", Age = 30 };

// Transform using ActionRef (for reference types, the object is modified)
Person updatedPerson = DelegateTransform.With(person, (ref Person p) => {
    p.Name = p.Name.ToUpper();
    p.Age += 1;
});

Console.WriteLine($"{updatedPerson.Name}, {updatedPerson.Age}"); // Outputs: JOHN, 31

// Transform using Func to create a string description
string description = DelegateTransform.With(person, p =>
    $"{p.Name} is {p.Age} years old");

Console.WriteLine(description); // Outputs: JOHN is 31 years old

API Reference

Delegate Types

// Custom delegate for actions on references
public delegate void ActionRef<T>(ref T item);

// Custom delegate for functions on references
public delegate T FuncRef<T>(ref T item);

DelegateTransform Static Class

The main class providing transformation methods.

Methods

Method Parameters Return Type Description
With<T> T input, ActionRef<T> delegate T Creates a copy, applies the action by reference, returns the modified copy
With<T> T input, Func<T, T> delegate T Applies a function to the input and returns the result
With<T> T input, FuncRef<T> delegate T Passes input by reference to the function and returns the result

All methods throw ArgumentNullException if the delegate is null.

Design Principles

Copy-on-Transform

The library follows a functional programming pattern where the original input is never mutated:

public static T With<T>(T input, ActionRef<T> @delegate)
{
    Ensure.NotNull(@delegate);

    T output = input;  // Creates a copy
    @delegate(ref output);
    return output;
}

This ensures predictable behavior and prevents side effects on the original values.

Performance Considerations

For value types (structs), a copy is made before transformation. For large structs where you want to avoid copying, consider using the FuncRef<T> overload which passes by reference and returns the modified value.

For reference types (classes), the "copy" is actually a copy of the reference, so the underlying object can be modified. If you need true immutability for reference types, create a new instance within your delegate.

Contributing

Contributions are welcome! Here's how you can help:

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Please make sure to update tests as appropriate and adhere to the existing coding style.

License

This project is licensed under the MIT License - see the LICENSE.md file for details.

No packages depend on ktsu.DelegateTransform.

## v1.1.4 (patch) Changes since v1.1.3: - Update project configuration files, add new workflows, and enhance SDK management ([@matt-edmondson](https://github.com/matt-edmondson)) - Refactor DelegateTransform methods for null checking and update project dependencies ([@matt-edmondson](https://github.com/matt-edmondson)) - Update project SDKs in DelegateTransform and DelegateTransform.Test to MSTest and Microsoft.NET.Sdk ([@matt-edmondson](https://github.com/matt-edmondson)) - Add CLAUDE.md for project guidance and documentation ([@matt-edmondson](https://github.com/matt-edmondson)) - Update .editorconfig, .gitignore, .runsettings, and PSBuild.psm1 for improved configurations and functionality ([@matt-edmondson](https://github.com/matt-edmondson)) ## v1.1.3 (patch) Changes since v1.1.2: - Update ktsu.ScopedAction package reference to version 1.1.2 ([@matt-edmondson](https://github.com/matt-edmondson)) ## v1.1.3-pre.17 (prerelease) Changes since v1.1.3-pre.16: - Sync .editorconfig ([@ktsu[bot]](https://github.com/ktsu[bot])) - Merge remote-tracking branch 'refs/remotes/origin/main' ([@ktsu[bot]](https://github.com/ktsu[bot])) - Sync scripts\PSBuild.psm1 ([@ktsu[bot]](https://github.com/ktsu[bot])) - Sync .gitattributes ([@ktsu[bot]](https://github.com/ktsu[bot])) - Sync .mailmap ([@ktsu[bot]](https://github.com/ktsu[bot])) - Sync .gitignore ([@ktsu[bot]](https://github.com/ktsu[bot])) - Sync .runsettings ([@ktsu[bot]](https://github.com/ktsu[bot])) ## v1.1.3-pre.16 (prerelease) Changes since v1.1.3-pre.15: - Sync .gitattributes ([@ktsu[bot]](https://github.com/ktsu[bot])) - Sync .editorconfig ([@ktsu[bot]](https://github.com/ktsu[bot])) - Sync .mailmap ([@ktsu[bot]](https://github.com/ktsu[bot])) - Sync .gitignore ([@ktsu[bot]](https://github.com/ktsu[bot])) - Sync scripts\PSBuild.psm1 ([@ktsu[bot]](https://github.com/ktsu[bot])) - Sync .runsettings ([@ktsu[bot]](https://github.com/ktsu[bot])) ## v1.1.3-pre.15 (prerelease) Changes since v1.1.3-pre.14: ## v1.1.3-pre.14 (prerelease) Changes since v1.1.3-pre.13: ## v1.1.3-pre.13 (prerelease) Changes since v1.1.3-pre.12: ## v1.1.3-pre.12 (prerelease) Changes since v1.1.3-pre.11: ## v1.1.3-pre.11 (prerelease) Changes since v1.1.3-pre.10: ## v1.1.3-pre.10 (prerelease) Changes since v1.1.3-pre.9: ## v1.1.3-pre.9 (prerelease) Changes since v1.1.3-pre.8: ## v1.1.3-pre.8 (prerelease) Changes since v1.1.3-pre.7: ## v1.1.3-pre.7 (prerelease) Changes since v1.1.3-pre.6: ## v1.1.3-pre.6 (prerelease) Changes since v1.1.3-pre.5: ## v1.1.3-pre.5 (prerelease) Changes since v1.1.3-pre.4: ## v1.1.3-pre.4 (prerelease) Changes since v1.1.3-pre.3: ## v1.1.3-pre.3 (prerelease) Changes since v1.1.3-pre.2: ## v1.1.3-pre.2 (prerelease) Changes since v1.1.3-pre.1: ## v1.1.3-pre.1 (prerelease) Incremental prerelease update. ## v1.1.2 (patch) Changes since v1.1.1: - Update README with detailed library introduction, features, usage examples, and API reference; change project SDK references in .csproj files to ktsu.Sdk.Lib and ktsu.Sdk.Test. ([@matt-edmondson](https://github.com/matt-edmondson)) - Remove Directory.Build.props and Directory.Build.targets files; add copyright headers to DelegateTransform and DelegateTransformTests; update variable declarations in tests for consistency; delete unused PowerShell scripts for metadata and version management. ([@matt-edmondson](https://github.com/matt-edmondson)) ## v1.1.2-pre.2 (prerelease) Changes since v1.1.2-pre.1: - Sync .github\workflows\dotnet.yml ([@ktsu[bot]](https://github.com/ktsu[bot])) - Sync .runsettings ([@ktsu[bot]](https://github.com/ktsu[bot])) - Sync .editorconfig ([@ktsu[bot]](https://github.com/ktsu[bot])) ## v1.1.2-pre.1 (prerelease) Incremental prerelease update. ## v1.1.1 (patch) Changes since v1.1.0: - Update packages ([@matt-edmondson](https://github.com/matt-edmondson)) ## v1.1.0 (minor) Changes since v1.0.0: - Apply new editorconfig ([@matt-edmondson](https://github.com/matt-edmondson)) - Add LICENSE template ([@matt-edmondson](https://github.com/matt-edmondson)) ## v1.0.2-pre.3 (prerelease) Changes since v1.0.2-pre.2: - Sync scripts\make-version.ps1 ([@ktsu[bot]](https://github.com/ktsu[bot])) - Sync scripts\make-changelog.ps1 ([@ktsu[bot]](https://github.com/ktsu[bot])) ## v1.0.2-pre.2 (prerelease) Changes since v1.0.2-pre.1: - Sync scripts\make-version.ps1 ([@ktsu[bot]](https://github.com/ktsu[bot])) - Sync .editorconfig ([@ktsu[bot]](https://github.com/ktsu[bot])) - Sync .gitignore ([@ktsu[bot]](https://github.com/ktsu[bot])) - Sync Directory.Build.targets ([@ktsu[bot]](https://github.com/ktsu[bot])) - Sync scripts\make-changelog.ps1 ([@ktsu[bot]](https://github.com/ktsu[bot])) ## v1.0.2-pre.1 (prerelease) Changes since v1.0.1: - Bump ktsu.ScopedAction from 1.0.14 to 1.0.15 in the ktsu group ([@dependabot[bot]](https://github.com/dependabot[bot])) ## v1.0.1 (patch) Changes since v1.0.0: - Apply new editorconfig ([@matt-edmondson](https://github.com/matt-edmondson)) ## v1.0.1-pre.16 (prerelease) Changes since v1.0.1-pre.15: - Sync scripts\make-version.ps1 ([@ktsu[bot]](https://github.com/ktsu[bot])) - Sync scripts\make-changelog.ps1 ([@ktsu[bot]](https://github.com/ktsu[bot])) ## v1.0.1-pre.15 (prerelease) Changes since v1.0.1-pre.14: - Sync .github\workflows\dotnet.yml ([@ktsu[bot]](https://github.com/ktsu[bot])) ## v1.0.1-pre.14 (prerelease) Changes since v1.0.1-pre.13: - Sync scripts\make-version.ps1 ([@ktsu[bot]](https://github.com/ktsu[bot])) - Sync scripts\make-changelog.ps1 ([@ktsu[bot]](https://github.com/ktsu[bot])) ## v1.0.1-pre.13 (prerelease) Changes since v1.0.1-pre.12: - Sync .github\workflows\dotnet.yml ([@ktsu[bot]](https://github.com/ktsu[bot])) ## v1.0.1-pre.12 (prerelease) Changes since v1.0.1-pre.11: - Sync .github\workflows\dotnet.yml ([@ktsu[bot]](https://github.com/ktsu[bot])) ## v1.0.1-pre.11 (prerelease) Changes since v1.0.1-pre.10: ## v1.0.1-pre.10 (prerelease) Changes since v1.0.1-pre.9: ## v1.0.1-pre.9 (prerelease) Changes since v1.0.1-pre.8: - Bump MSTest from 3.7.2 to 3.7.3 ([@dependabot[bot]](https://github.com/dependabot[bot])) ## v1.0.1-pre.8 (prerelease) Changes since v1.0.1-pre.7: ## v1.0.1-pre.7 (prerelease) Changes since v1.0.1-pre.6: ## v1.0.1-pre.6 (prerelease) Changes since v1.0.1-pre.5: - Bump MSTest from 3.7.1 to 3.7.2 ([@dependabot[bot]](https://github.com/dependabot[bot])) ## v1.0.1-pre.5 (prerelease) Changes since v1.0.1-pre.4: - Bump coverlet.collector from 6.0.3 to 6.0.4 ([@dependabot[bot]](https://github.com/dependabot[bot])) ## v1.0.1-pre.4 (prerelease) Changes since v1.0.1-pre.3: ## v1.0.1-pre.3 (prerelease) Changes since v1.0.1-pre.2: ## v1.0.1-pre.2 (prerelease) Changes since v1.0.1-pre.1: - Bump MSTest from 3.7.0 to 3.7.1 ([@dependabot[bot]](https://github.com/dependabot[bot])) ## v1.0.1-pre.1 (prerelease) Incremental prerelease update. ## v1.0.0 (major) No significant changes detected since v0.0.1-pre.1. ## v0.0.1-pre.1 (prerelease) Changes since 0.0.1.0: - Add AllowEmptyCollection attribute to SEARCH_TAGS parameter in MakeNotesForRange function ([@matt-edmondson](https://github.com/matt-edmondson)) - Enable debugging trace in changelog and version scripts ([@matt-edmondson](https://github.com/matt-edmondson)) - Set default version to 'v1.0.0-pre.0' if no tags are found ([@matt-edmondson](https://github.com/matt-edmondson)) - Fix formatting issues and handle empty tag scenarios in changelog script ([@matt-edmondson](https://github.com/matt-edmondson)) - Enhance GitHub Actions workflow by enabling LFS and fetching tags ([@matt-edmondson](https://github.com/matt-edmondson)) - Initial commit ([@matt-edmondson](https://github.com/matt-edmondson)) - Refactor tag handling in changelog and version scripts to ensure default values are set correctly when no tags are found ([@matt-edmondson](https://github.com/matt-edmondson))

Version Downloads Last updated
1.1.5-pre.2 5 01/28/2026
1.1.5-pre.1 49 01/26/2026
1.1.4 50 01/26/2026