Monday, March 9, 2026

C# - a callable with custom data

Have you ever wondered if a C# delegate can contain a custom field or property?

No, it can't, classes that are delegates are closed for extensions - one would say.

In other words, C# can't mimick JavaScript, where you can attach anything to a function - this pattern is useful when implementing some functional patterns like memoization.

A side note - TypeScript is flexible enough, you can have a type that describes an object that is callable and yet contains some data:

type Callable = {
    description: string;
    (a: string): string;
}

But let's go back to C#. Is it really not possible? Well, not directly. However, there's a clever way of forcing an object of any shape to be implicitely convertible to a function type. And this implicit conversion would take place when the object would be passed to an auxiliary function, as an argument!

public class Program
{
	/// 
	/// Auxiliary executor
	/// 
	static string Executor(Func<string, string> logic, string input)
	{
		return logic(input); 
	}

	static void Main(string[] args)
	{
		Callable c = new Callable()
		{
			Description = "custom description"
		};

		string result = Executor(c, "FooBar");
		Console.WriteLine(result);
	}
}

public class Callable
{
	public string Description { get; set; }

	/// 
	/// Internal implementation details of the "callable" interface
	/// 
	private string Invoke(string param) => $"Argument: {param}, this.Description: {Description}";

	/// 
	/// Public implicit conversion
	/// 
	public static implicit operator Func<string, string>(Callable c) => c.Invoke;
}