C# Delegates ported to ROBLOX!

C# delegates can call multiple functions with a single function call

-- C# Code
using System;

public class DelegateExample
{
    // Delegate declaration
    public delegate void MyDelegate(string message);

    // Method matching the delegate signature
    public static void DisplayMessage(string msg)
    {
        Console.WriteLine("Message: " + msg);
    }

    public static void DisplayMessageButDifferent(string msg)
    {
        Console.WriteLine("Message but different: " + msg);
    }

    public static void Main()
    {
        // Instantiating delegate
        MyDelegate del = DisplayMessage;
        del += DisplayMessageButDifferent
        // Invoking delegate
        del("Hello from delegate!");
        
    }
}

--- Should print both messages idk i didnt test this out yet

this functionality is now in ROBLOX with the delegate module!

How to use

Start off by requiring the module

local delegateModule = -- wherever you placed it, i prefer to place it in ReplicatedStorage

Then create a new delegate with a constructor method

(we’ll use the normal one for now)

local delegate = delegateModule.new ()

Then add more functions!

function Function1 (message : string)
	print ("Function 1 says ", message)
end

function Function2 (message : string)
	print ("Function 2 says ", message)
end

function Function3 (message : string)
	print ("Function 3 says ", message)
end

function Function4 (message : string)
	print ("Function 4 says ", message)
end

local delegate = delegateClass.new ()

delegate += Function1
delegate += Function2
delegate += Function3
delegate += Function4

-- You can also do 
-- delegateClass.new (Function1, Function2) so on and so forth

To call all of the functions, just call the delegate like it’s a function

delegate("something")

image
all functions fire at basically the exact same time!

You can also remove functions by using the minus sign, I will show that later

This works because delegates are really just empty tables with metatables

__add = function () ... end
__sub = function () ... end
__call = function () ... end
__len = function () ... end

Speaking of __len (length) you can check how many listeners a delegate has by putting a hashtag in front of the delegate


delegate += Function1
delegate += Function2
delegate += Function3
delegate += Function4

delegate ("something")
print (#delegate)
 

image


The other constructor?

The delegate module has another constructor function beside new

DelegateConstructor.fromTable

as the name suggests, this function creates a new delegate out of a table of functions

local Functions = {
	Function1,
	Function2,
	Function3,
	Function4
}

local delegate = delegateClass.fromTable (Functions)

and it still works the exact same!
image

i reused the same picture btw just know it still works the same


Example:


local rs = game:GetService ("ReplicatedStorage")
local delegateClass = require (rs:WaitForChild ("Delegate"))

function Function5 (color : BrickColor)
	print ("And function 5 will never be called")
end

-- Creates a new delegate and populates it with listeners

local delegate = delegateClass.new (
	-- Function stack?
	
	function (color : BrickColor)
		print ("Function 1 prints the color ", color.Name)
	end,
	
	function (color : BrickColor)
		print ("Function 2 creates a cube with the color ", color.Name)
		
		local Part = Instance.new ("Part")
		
		Part.Parent = workspace
		Part.Size = Vector3.one * 4
		Part.Position = Vector3.yAxis * 5
		Part.BrickColor = color
	end,

	function (color : BrickColor)
		print ("Function 3 creates a ball with the color ", color.Name)

		local Part = Instance.new ("Part")

		Part.Parent = workspace
		Part.Size = Vector3.one * 4
		Part.Position = Vector3.yAxis * 10
		Part.BrickColor = color
		Part.Shape = "Ball"
	end,
	
	function (color : BrickColor)
		print ("Function 4 creates turns the baseplate ", color.Name)

		workspace.Baseplate.BrickColor = color
	end,
	
	Function5

)

-- Removing Function5 from the delegate
-- So Function5 will not be called when the delegate is called
delegate -= Function5

task.wait (1)
delegate (BrickColor.random())

you cant guess the color this is


Installation:

https://create.roblox.com/store/asset/77185318977897/Delegate-v011

10 Likes

Neat. Delegates are nice. Although, we already have BindableEvents and signal types. Why should this be used over one of those?

1 Like

i do not know sasdasda

2 Likes

At least you’re honest

It’s a nice take on the average Signal type. I do prefer +=. I’ll probably stick to bindable events and signals, but it’s nice to have options that take inspiration from other languages.

1 Like

I guess the syntax is easier for people who aren’t that good at scripting

1 Like

lol

I think overloading operators to do weird things like what delegates do is actually an anti-pattern. Operator overloading should only be used when it’s obvious what the operator will do. If it’s not obvious, just use a function or a custom operator. Custom operator…That’s one thing I want that most mainstream languages will never add.

I think it’s pretty easy to figure out that + sign adds stuff while - sign removes it

Yeah, but if foo is of type A, I expect += to add another A to it. Saying .listen is better because it is unambiguous what it does.

1 Like

its like 10 times easier to just call the functions consecutively but ok

1 Like

yeah i guess that is fairrrrrrr

2 Likes

also if the language (not luau :pensive:) supports custom operators, you could make your own operator that is not += so you get to have your fancy symbol heavy code without being ambiguous!!!1!

Or to just use a signal library.
Or to just use bindable events.
Or to just make a wrapper function.

practically every single symbol is taken theres not much options

custom operators can have multiple symbols in them. For instance, #> could be used.

Scala is an “imperative” language that has support for them, if you want to try them in actual code.

or just do this like an evil person

function AllTheFunctionsMuahahah()
       Function1()
       Function2()
end)
4 Likes

just enjoy the moduleeeeeeeeeeeee

2 Likes

I was going to make a joke here, but then I forgot you can’t read!

1 Like

yeah i was too stupid to understand what wrapper function meant but now i get it

1 Like

but you cant change the functions that would be called at runtime with this method so my module actually DOES have a use

2 Likes

Yeah, it does. It’s a nice alternate syntax to Signals/BindableEvents.

no it doesntttttttttttttttttttt

1 Like