{"id":19789563,"url":"https://github.com/webfreak001/multicast-delegate","last_synced_at":"2026-03-05T00:05:13.302Z","repository":{"id":146627973,"uuid":"265556250","full_name":"WebFreak001/multicast-delegate","owner":"WebFreak001","description":"C-Sharp style MulticastDelegate, allows combining and calling multiple delegates into one","archived":false,"fork":false,"pushed_at":"2020-05-20T13:01:20.000Z","size":8,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-11T04:13:12.090Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"D","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/WebFreak001.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-20T12:19:53.000Z","updated_at":"2020-05-21T00:25:27.000Z","dependencies_parsed_at":"2023-04-25T00:46:38.469Z","dependency_job_id":null,"html_url":"https://github.com/WebFreak001/multicast-delegate","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebFreak001%2Fmulticast-delegate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebFreak001%2Fmulticast-delegate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebFreak001%2Fmulticast-delegate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebFreak001%2Fmulticast-delegate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WebFreak001","download_url":"https://codeload.github.com/WebFreak001/multicast-delegate/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241126633,"owners_count":19914053,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-12T06:33:55.910Z","updated_at":"2026-03-05T00:05:12.835Z","avatar_url":"https://github.com/WebFreak001.png","language":"D","funding_links":[],"categories":[],"sub_categories":[],"readme":"# multicast-delegate\r\n\r\nC-Sharp style MulticastDelegate, allows combining and calling multiple delegates\r\ninto one. Transparently works with third party libraries, works with `@safe`,\r\n`nothrow`, `pure` and has APIs to use with `@nogc`. The library works well with\r\n`const` and `immutable` as well and the data structure is simply a safe and\r\nefficient wrapper around delegate arrays. Offers consistent D-style operator\r\noverloading using the `~` concatenation operator as well as C# compatible `+`\r\nand `-` operators for calling the add and remove functions.\r\n\r\n* Allows you to define APIs with more flexible callbacks\r\n* Allows you to use this as C# style event system\r\n* Allows you to write arbitrary depth callbacks with return values and out/ref\r\n* Uses idiomatic features with full integration of language features\r\n\r\nTo use in your dub project simply run\r\n```\r\ndub add multicast-delegate\r\n```\r\n\r\nTo use with additional C# compatibility types, add\r\n```js\r\n\"subConfigurations\": {\r\n\t\"multicast-delegate\": \"cs-compat\"\r\n}\r\n```\r\nto your dub.json or add\r\n```sdl\r\n// dub.sdl\r\nsubConfiguration \"multicast-delegate\" \"cs-compat\"\r\n```\r\nto your dub.sdl.\r\n\r\nTo use elsewhere, just copy the\r\n[source/multicast_delegate.d](source/multicast_delegate.d) file into your\r\nproject and import it using `import multicast_delegate`.\r\n\r\n## Example\r\n\r\n```d\r\nimport std.stdio;\r\nimport multicast_delegate; // I recommend using `public import` for all\r\n                           // your common imports in some helper file\r\n\r\n// have documented delegate types for your callbacks\r\nalias SomeDelegate = void delegate();\r\n\r\n// define your APIs as usual\r\nvoid runCallback(SomeDelegate dg) { dg(); }\r\n\r\nvoid main() {\r\n\tvoid func1() { writeln(\"1\"); }\r\n\tvoid func2() { writeln(\"2\"); }\r\n\r\n\twriteln(\"\\ncalling normal delegate\");\r\n\t\t// call like normal\r\n\t\trunCallback(\u0026func1);\r\n\r\n\twriteln(\"\\ncalling multicast delegates\");\r\n\t\t// or call with multiple delegates in a row\r\n\t\trunCallback(multicast(\u0026func1, \u0026func2));\r\n\r\n\twriteln(\"\\ncalling more delegates\");\r\n\t\t// or store more complex delegate groups\r\n\t\tMulticast!SomeDelegate multi = \u0026func1;\r\n\t\t// mutate it!\r\n\t\tmulti ~= \u0026func2;\r\n\r\n\t\t// or construct it immutable or const\r\n\t\timmutable Multicast!SomeDelegate fixed = multicast(\u0026func2, \u0026func2);\r\n\r\n\t\t// concat multiple and call a normal delegate method\r\n\t\trunCallback(multi ~ fixed); // implicitly using Multicast!T as delegate\r\n}\r\n```\r\n\r\noutputs\r\n```\r\ncalling normal delegate\r\n1\r\n\r\ncalling multicast delegates\r\n1\r\n2\r\n\r\ncalling more delegates\r\n1\r\n2\r\n2\r\n2\r\n```\r\n\r\nAnother simple example porting the following C# code:\r\n```cs\r\nusing System;\r\n\r\npublic class Program\r\n{\r\n\tpublic delegate void SomeDelegate();\r\n\r\n\tpublic static void Main()\r\n\t{\r\n\t\tvoid Foo() { Console.WriteLine(\"foo\"); }\r\n\t\tvoid Bar() { Console.WriteLine(\"bar\"); }\r\n\r\n\t\tSomeDelegate dg = Foo;\r\n\t\tdg += Foo;\r\n\t\tdg += Foo;\r\n\t\tdg += Bar;\r\n\t\tdg();\r\n\r\n\t\tCallCB(dg);\r\n\t}\r\n\r\n\tpublic static void CallCB(SomeDelegate cb)\r\n\t{\r\n\t\tcb();\r\n\t}\r\n}\r\n```\r\n\r\nis ported:\r\n```d\r\nimport std.stdio;\r\nimport multicast_delegate;\r\n\r\nalias SomeDelegate = void delegate();\r\n\r\nvoid main()\r\n{\r\n\tvoid foo() { writeln(\"foo\"); }\r\n\tvoid bar() { writeln(\"bar\"); }\r\n\r\n\tMulticast!SomeDelegate dg = \u0026foo;\r\n\tdg ~= \u0026foo;\r\n\tdg ~= \u0026foo;\r\n\tdg ~= \u0026bar;\r\n\tdg();\r\n\r\n\tcallCB(dg);\r\n}\r\n\r\nvoid callCB(SomeDelegate cb)\r\n{\r\n\tcb();\r\n}\r\n```\r\n\r\nIf you want to use global functions (not delegates) you need to\r\n`import std.functional : toDelegate` and use `dg ~= toDelegate(\u0026foo);`\r\nor you can define `SomeDelegate` as a `void function()`. However in this exact\r\ncode the callCB function argument would break with that.\r\n\r\nUsing class or struct members and lambdas works without issues.\r\n\r\n## Documentation\r\n\r\n[https://multicast-delegate.dpldocs.info](https://multicast-delegate.dpldocs.info)\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebfreak001%2Fmulticast-delegate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwebfreak001%2Fmulticast-delegate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebfreak001%2Fmulticast-delegate/lists"}