diff --git a/README.md b/README.md index e4aefaa3d..facaaafa2 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# RSCG - 255 Examples of Roslyn Source Code Generators / 16 created by Microsoft / +# RSCG - 256 Examples of Roslyn Source Code Generators / 16 created by Microsoft / -The RSCG_Examples repository is a comprehensive documentation system that automatically processes and showcases 255 Roslyn Source Code Generator (RSCG) examples. The system transforms individual RSCG projects into structured documentation with code examples and cross-referenced content with a searchable website and code example exports. +The RSCG_Examples repository is a comprehensive documentation system that automatically processes and showcases 256 Roslyn Source Code Generator (RSCG) examples. The system transforms individual RSCG projects into structured documentation with code examples and cross-referenced content with a searchable website and code example exports. This system serves as both a learning resource for .NET developers interested in source generators and an automated pipeline for maintaining up-to-date documentation about the RSCG ecosystem -## Latest Update : 2026-02-13 => 13 February 2026 +## Latest Update : 2026-02-14 => 14 February 2026 If you want to see examples with code, please click ***[List V2](https://ignatandrei.github.io/RSCG_Examples/v2/docs/List-of-RSCG)*** @@ -24,8 +24,30 @@ If you want to be notified each time I add a new RSCG example , please click htt ## Content -Those are the 255 Roslyn Source Code Generators that I have tested you can see and download source code example. +Those are the 256 Roslyn Source Code Generators that I have tested you can see and download source code example. ( including 16 from Microsoft ) +### 256. [Sundew.DiscriminatedUnions](https://ignatandrei.github.io/RSCG_Examples/v2/docs/Sundew.DiscriminatedUnions) , in the [FunctionalProgramming](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#functionalprogramming) category + +Generated on : 2026-02-14 => 14 February 2026 + +
+ Expand + + + +Author: Kim Hugener Ohlsen + + + +Nuget: [https://www.nuget.org/packages/Sundew.DiscriminatedUnions/](https://www.nuget.org/packages/Sundew.DiscriminatedUnions/) + + +Link: [https://ignatandrei.github.io/RSCG_Examples/v2/docs/Sundew.DiscriminatedUnions](https://ignatandrei.github.io/RSCG_Examples/v2/docs/Sundew.DiscriminatedUnions) + +Source: [https://github.com/sundews/Sundew.DiscriminatedUnions](https://github.com/sundews/Sundew.DiscriminatedUnions) + +
+ ### 255. [KnockOff](https://ignatandrei.github.io/RSCG_Examples/v2/docs/KnockOff) , in the [Tests](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#tests) category Generated on : 2026-02-13 => 13 February 2026 diff --git a/later.md b/later.md index 6b1ece8f7..c04831d49 100644 --- a/later.md +++ b/later.md @@ -1,6 +1,6 @@ # Just later -## Latest Update : 2026-02-13 => 13 February 2026 +## Latest Update : 2026-02-14 => 14 February 2026 diff --git a/v2/Generator/MultiGeneratorV2.cs b/v2/Generator/MultiGeneratorV2.cs index 1882bc3c0..571b8bd2c 100644 --- a/v2/Generator/MultiGeneratorV2.cs +++ b/v2/Generator/MultiGeneratorV2.cs @@ -227,6 +227,7 @@ public string[] SourceNoRSCG() text = text.Replace("(skills/", $"({d.Generator!.Source}/skills"); text = text.Replace("Access them as a ReadOnlySpan", "Access them as a ReadOnlySpan\\"); + text = text.Replace("", "\\"); text = text.Replace("### ", "##### "); text = text.Replace("## ", "#### "); text = text.Replace("# ", "### "); diff --git a/v2/Generator/all.csv b/v2/Generator/all.csv index 7623fc5a3..cf6e6e590 100644 --- a/v2/Generator/all.csv +++ b/v2/Generator/all.csv @@ -254,3 +254,4 @@ Nr,Key,Source,Category 253,FastCloner, https://github.com/lofcz/FastCloner/,Clone 254,ErrorOrX, https://github.com/ANcpLua/ErrorOrX,API 255,KnockOff, https://github.com/NeatooDotNet/KnockOff,Tests +256,Sundew.DiscriminatedUnions, https://github.com/sundews/Sundew.DiscriminatedUnions,FunctionalProgramming diff --git a/v2/RSCGExamplesData/GeneratorDataRec.json b/v2/RSCGExamplesData/GeneratorDataRec.json index baa03019d..06f285fc0 100644 --- a/v2/RSCGExamplesData/GeneratorDataRec.json +++ b/v2/RSCGExamplesData/GeneratorDataRec.json @@ -1546,5 +1546,11 @@ "Category": 13, "dtStart": "2026-02-13T00:00:00", "show": true + }, + { + "ID":"Sundew.DiscriminatedUnions", + "Category": 10, + "dtStart": "2026-02-14T00:00:00", + "show": true } ] \ No newline at end of file diff --git a/v2/book/examples/Sundew.DiscriminatedUnions.html b/v2/book/examples/Sundew.DiscriminatedUnions.html new file mode 100644 index 000000000..20f69d704 --- /dev/null +++ b/v2/book/examples/Sundew.DiscriminatedUnions.html @@ -0,0 +1,75 @@ + +

RSCG nr 256 : Sundew.DiscriminatedUnions

+ +

Info

+Nuget : https://www.nuget.org/packages/Sundew.DiscriminatedUnions/ + +

You can find more details at : https://github.com/sundews/Sundew.DiscriminatedUnions

+ +

Author :Kim Hugener Ohlsen

+ +

Source: https://github.com/sundews/Sundew.DiscriminatedUnions

+ +

About

+ +Generate tagged union + +

+ How to use +

+

+ Add reference to the Sundew.DiscriminatedUnions in the csproj +

+ + +

This was for me the starting code

+ +
+ I have coded the file Program.cs +
+ +
+ +
+ I have coded the file ResultSave.cs +
+ +
+ +
+ I have coded the file SaveToDatabase.cs +
+ +
+

And here are the generated files

+ +
+ The file generated is UnionTypesDemo.ResultSave.generated.cs +
+ + +
+ The file generated is UnionTypesDemo.ResultSave.NotFound.generated.cs +
+ + +
+ The file generated is UnionTypesDemo.ResultSave.Ok.generated.cs +
+ + +

+ You can download the code and this page as pdf from + + https://ignatandrei.github.io/RSCG_Examples/v2/docs/Sundew.DiscriminatedUnions + +

+ + +

+ You can see the whole list at + + https://ignatandrei.github.io/RSCG_Examples/v2/docs/List-of-RSCG + +

+ diff --git a/v2/book/list.html b/v2/book/list.html index 71c549521..a77aa33b4 100644 --- a/v2/book/list.html +++ b/v2/book/list.html @@ -17,7 +17,7 @@

-This is the list of 255 RSCG with examples => +This is the list of 256 RSCG with examples =>

@@ -1046,6 +1046,10 @@

+ + + +
255 KnockOff
256Sundew.DiscriminatedUnions
diff --git a/v2/book/pandocHTML.yaml b/v2/book/pandocHTML.yaml index be7df0edb..53156b762 100644 --- a/v2/book/pandocHTML.yaml +++ b/v2/book/pandocHTML.yaml @@ -269,6 +269,7 @@ input-files: - examples/FastCloner.html - examples/ErrorOrX.html - examples/KnockOff.html +- examples/Sundew.DiscriminatedUnions.html # or you may use input-file: with a single value # defaults: diff --git a/v2/rscg_examples/Sundew.DiscriminatedUnions/description.json b/v2/rscg_examples/Sundew.DiscriminatedUnions/description.json new file mode 100644 index 000000000..16a858449 --- /dev/null +++ b/v2/rscg_examples/Sundew.DiscriminatedUnions/description.json @@ -0,0 +1,22 @@ +{ + "generator":{ + "name":"Sundew.DiscriminatedUnions", + "nuget":[ + "https://www.nuget.org/packages/Sundew.DiscriminatedUnions/" + ], + "link":"https://github.com/sundews/Sundew.DiscriminatedUnions", + "author":"Kim Hugener Ohlsen", + "source":"https://github.com/sundews/Sundew.DiscriminatedUnions" + }, + "data":{ + "goodFor":["Generate tagged union"], + "csprojDemo":"UnionTypesDemo.csproj", + "csFiles":["Program.cs","ResultSave.cs","SaveToDatabase.cs"], + "excludeDirectoryGenerated":[""], + "includeAdditionalFiles":[""] + }, + "links":{ + "blog":"", + "video":"" + } +} \ No newline at end of file diff --git a/v2/rscg_examples/Sundew.DiscriminatedUnions/readme.txt b/v2/rscg_examples/Sundew.DiscriminatedUnions/readme.txt new file mode 100644 index 000000000..9fdb619a8 --- /dev/null +++ b/v2/rscg_examples/Sundew.DiscriminatedUnions/readme.txt @@ -0,0 +1,130 @@ +# Discriminated Unions + +Sundew.DiscriminatedUnions implement discriminated unions for C#, until a future version of C# provides it out of the box. +The idea is that this package can be deleted once unions are supported in C#, without requiring changes to switch expressions and statements. + +In addition, the project supports dimensional unions through default interface methods (traits). +A dimensional union is a union where cases can be reused in any number of unions, by supporting interface unions through the possibility of implementing multiple interface and default interface members. + +## How it works +A Roslyn analyzer asserts and report errors in case switch statements or switch expression do not handle all cases. +C# 8 and 9 already comes with great pattern matching support for evaluation. + +In order that the inheritance hierarchy remain closed (All cases in the same assembly), an analyzer ensures that unions are not derived from in referencing assemblies. +Similarly all case classes should be sealed. + +Create a union by inheriting from an abstract base (record) class (or interface) marked with the DiscriminatedUnion attribute to build various cases. +Either specify the partial keyword to the union for a source generator to implement factory methods or use the codefix PDU0001 to generate them. + +## Sample +### Defining a union +```csharp +[Sundew.DiscriminatedUnions.DiscriminatedUnion] +public abstract partial record Result +{ + public sealed partial record Success : Result; + + public sealed partial record Warning(string Message) : Result; + + public sealed partial record Error(int Code) : Result; +} +``` +Alternatively, a union can be defined with unnested case classes and interfaces, allowing the possibility of creating dimensional unions (see below). + +### Evaluation +```csharp +var message = result switch +{ + Result.Error { Code: > 70 } error => $"High Error code: {error.Code}", + Result.Error error => $"Error code: {error.Code}", + Result.Warning { Message: "Tough warning" } => "Not good", + Result.Warning warning => warning.Message, + Result.Success => "Great", +}; +``` + +### Dimensional unions +To support dimensional unions, unnested cases help because the cases are no longer defined inside a union. However, for this to work the unions are required to declare a factory method named exactly like the case type and that has the CaseType attribute specifying the actual type. +Since version 3, factory methods are generated when the union is declared partial. Alternatively, a code fix (PDU0001) is available to generate the factory methods. + +```csharp +[Sundew.DiscriminatedUnions.DiscriminatedUnion] +public partial interface IExpression; + +[Sundew.DiscriminatedUnions.DiscriminatedUnion] +public partial interface IArithmeticExpression : IExpression; + +[Sundew.DiscriminatedUnions.DiscriminatedUnion] +public partial interface ICommutativeExpression : IArithmeticExpression; + +public sealed partial record AdditionExpression(IExpression Lhs, IExpression Rhs) : ICommutativeExpression; + +public sealed partial record SubtractionExpression(IExpression Lhs, IExpression Rhs) : IArithmeticExpression; + +public sealed partial record MultiplicationExpression(IExpression Lhs, IExpression Rhs) : ICommutativeExpression; + +public sealed partial record DivisionExpression(IExpression Lhs, IExpression Rhs) : IArithmeticExpression; + +public sealed partial record ValueExpression(int Value) : IExpression; +``` + +#### Evaluating dimensional unions +With dimensional unions it is possible to handle all cases using a sub union. +As seen in the example below, handling the ArithmeticExpression covers Addition-, Subtraction-, Multiplication- and DivisionExpression. +Typically one would dispatch these to a method handling ArithmeticExpression and where handling all cases would be checked, but it is not required. +This makes it convienient to separate handling logic in smaller chucks of code. + +```csharp +public int Evaluate(Expression expression) +{ + return expression switch + { + ArithmeticExpression arithmeticExpression => Evaluate(arithmeticExpression), + ValueExpression valueExpression => valueExpression.Value, + }; +} + +public int Evaluate(ArithmeticExpression arithmeticExpression) +{ + return arithmeticExpression switch + { + AdditionExpression additionExpression => Evaluate(additionExpression.Lhs) + Evaluate(additionExpression.Rhs), + SubtractionExpression subtractionExpression => Evaluate(subtractionExpression.Lhs) - Evaluate(subtractionExpression.Rhs), + MultiplicationExpression multiplicationExpression => Evaluate(multiplicationExpression.Lhs) * Evaluate(multiplicationExpression.Rhs), + DivisionExpression divisionExpression => Evaluate(divisionExpression.Lhs) / Evaluate(divisionExpression.Rhs), + }; +} +``` + +#### Enum evaluation +As of version 5.1, regular enums can also use the DiscriminatedUnion attribute causing the analyzer to exhaustively check switch statements and expressions. + +## Generator features +As mentioned a source generator is automatically activated for generating factory methods when the partial keyword is specified. +In addition, the DiscriminatedUnion attribute can specify a flags enum (GeneratorFeatures) to control additional code generation. + +* Segregate - Generates an extension method for IEnumerable that segregates all items into buckets of the different result. + +## Supported diagnostics: +| Diagnostic Id | Description | Code Fix | +| ------------- | ------------------------------------------------------------------------------------------------------------------------- | :------: | +| SDU0001 | Switch does not handled all cases | yes | +| SDU0002 | Switch should not handle default case | yes | +| SDU0003 | Switch has unreachable null case | yes | +| SDU0004 | Class unions must be abstract | yes | +| SDU0005 | Only unions can extended other unions | no | +| SDU0006 | Unions cannot be extended outside their assembly | no | +| SDU0007 | Cases must be declared in the same assembly as their unions | no | +| SDU0008 | Cases should be sealed | yes | +| SDU0009 | Unnested cases should have factory method | PDU0001 | +| SDU0010 | Factory method should have correct CaseTypeAttribute | yes | +| SDU0011 | Reported when a case is implemented by throwing NotImplementedException, because CodeCleanup may siliently 'fix' SDU0001. | yes | +| SDU0012 | Reported when a case contains type parameters that are not in the union type parameter list. | yes | +| PDU0001 | Make union/case partial for code generator | yes | +| PDU0002 | Populate union factory methods | yes | +| SDU9999 | Switch should throw in default case | no | +| GDU0001 | Discriminated union declaration could not be found | no | + +## Issues/Todos +* Switch appears with red squiggly lines in VS: https://github.com/dotnet/roslyn/issues/57041 +* Nullability is falsely evaluated when the switch hints null is possible: https://github.com/dotnet/roslyn/issues/57042 \ No newline at end of file diff --git a/v2/rscg_examples/Sundew.DiscriminatedUnions/src/.tours/Sundew.DiscriminatedUnions.tour b/v2/rscg_examples/Sundew.DiscriminatedUnions/src/.tours/Sundew.DiscriminatedUnions.tour new file mode 100644 index 000000000..42a4d0de8 --- /dev/null +++ b/v2/rscg_examples/Sundew.DiscriminatedUnions/src/.tours/Sundew.DiscriminatedUnions.tour @@ -0,0 +1,54 @@ + +{ + "$schema": "https://aka.ms/codetour-schema", + "title": "Sundew.DiscriminatedUnions", + "steps": + [ + { + "file": "UnionTypesDemo/UnionTypesDemo.csproj", + "description": "First, we add Nuget [Sundew.DiscriminatedUnions](https://www.nuget.org/packages/Sundew.DiscriminatedUnions/) in csproj ", + "pattern": "Sundew.DiscriminatedUnions" + } + + ,{ + "file": "UnionTypesDemo/SaveToDatabase.cs", + "description": "File SaveToDatabase.cs ", + "pattern": "this is the code" + } + + ,{ + "file": "UnionTypesDemo/ResultSave.cs", + "description": "File ResultSave.cs ", + "pattern": "this is the code" + } + + ,{ + "file": "UnionTypesDemo/Program.cs", + "description": "File Program.cs \r\n>> dotnet run --project UnionTypesDemo/UnionTypesDemo.csproj ", + "pattern": "this is the code" + } + + + ,{ + "file": "UnionTypesDemo/obj/GX/Sundew.DiscriminatedUnions.Generator/Sundew.DiscriminatedUnions.Generator.DiscriminatedUnionGenerator/UnionTypesDemo.ResultSave.Ok.generated.cs", + "description": "Generated File 3 from 3 : UnionTypesDemo.ResultSave.Ok.generated.cs ", + "line": 1 + } + + ,{ + "file": "UnionTypesDemo/obj/GX/Sundew.DiscriminatedUnions.Generator/Sundew.DiscriminatedUnions.Generator.DiscriminatedUnionGenerator/UnionTypesDemo.ResultSave.NotFound.generated.cs", + "description": "Generated File 2 from 3 : UnionTypesDemo.ResultSave.NotFound.generated.cs ", + "line": 1 + } + + ,{ + "file": "UnionTypesDemo/obj/GX/Sundew.DiscriminatedUnions.Generator/Sundew.DiscriminatedUnions.Generator.DiscriminatedUnionGenerator/UnionTypesDemo.ResultSave.generated.cs", + "description": "Generated File 1 from 3 : UnionTypesDemo.ResultSave.generated.cs ", + "line": 1 + } + + ], + + "ref": "main" + +} \ No newline at end of file diff --git a/v2/rscg_examples/Sundew.DiscriminatedUnions/src/UnionTypesDemo.sln b/v2/rscg_examples/Sundew.DiscriminatedUnions/src/UnionTypesDemo.sln new file mode 100644 index 000000000..d7021d30f --- /dev/null +++ b/v2/rscg_examples/Sundew.DiscriminatedUnions/src/UnionTypesDemo.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34221.43 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnionTypesDemo", "UnionTypesDemo\UnionTypesDemo.csproj", "{B3F52D30-D0FB-4DF2-B494-6B903B16613D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B3F52D30-D0FB-4DF2-B494-6B903B16613D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B3F52D30-D0FB-4DF2-B494-6B903B16613D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B3F52D30-D0FB-4DF2-B494-6B903B16613D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B3F52D30-D0FB-4DF2-B494-6B903B16613D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7C63CD9F-20A2-4EAB-9766-127A7184E23B} + EndGlobalSection +EndGlobal diff --git a/v2/rscg_examples/Sundew.DiscriminatedUnions/src/UnionTypesDemo/Program.cs b/v2/rscg_examples/Sundew.DiscriminatedUnions/src/UnionTypesDemo/Program.cs new file mode 100644 index 000000000..8a4f87cd4 --- /dev/null +++ b/v2/rscg_examples/Sundew.DiscriminatedUnions/src/UnionTypesDemo/Program.cs @@ -0,0 +1,17 @@ +using UnionTypesDemo; + +Console.WriteLine("Save or not"); +ResultSave data = SaveToDatabase.Save(0); +var message= data switch +{ + ResultSave.Ok ok => $"Saved {ok.i}", + ResultSave.NotFound => "Not found", +}; +Console.WriteLine(message); +data = SaveToDatabase.Save(1); +message = data switch +{ + ResultSave.Ok ok => $"Saved {ok.i}", + ResultSave.NotFound => "Not found", +}; +Console.WriteLine(message); diff --git a/v2/rscg_examples/Sundew.DiscriminatedUnions/src/UnionTypesDemo/ResultSave.cs b/v2/rscg_examples/Sundew.DiscriminatedUnions/src/UnionTypesDemo/ResultSave.cs new file mode 100644 index 000000000..5ec237fe6 --- /dev/null +++ b/v2/rscg_examples/Sundew.DiscriminatedUnions/src/UnionTypesDemo/ResultSave.cs @@ -0,0 +1,16 @@ + +using Sundew.DiscriminatedUnions; + +namespace UnionTypesDemo; + + +[DiscriminatedUnion] +public abstract partial record ResultSave +{ + + public sealed partial record Ok(int i) : ResultSave; + + public sealed partial record NotFound():ResultSave ; + +} + diff --git a/v2/rscg_examples/Sundew.DiscriminatedUnions/src/UnionTypesDemo/SaveToDatabase.cs b/v2/rscg_examples/Sundew.DiscriminatedUnions/src/UnionTypesDemo/SaveToDatabase.cs new file mode 100644 index 000000000..1d58dea12 --- /dev/null +++ b/v2/rscg_examples/Sundew.DiscriminatedUnions/src/UnionTypesDemo/SaveToDatabase.cs @@ -0,0 +1,16 @@ +namespace UnionTypesDemo; + +public class SaveToDatabase +{ + public static ResultSave Save(int i) + { + + if (i == 0) + { + return ResultSave._NotFound; + } + return ResultSave._Ok(i); + } +} + + diff --git a/v2/rscg_examples/Sundew.DiscriminatedUnions/src/UnionTypesDemo/UnionTypesDemo.csproj b/v2/rscg_examples/Sundew.DiscriminatedUnions/src/UnionTypesDemo/UnionTypesDemo.csproj new file mode 100644 index 000000000..afacc6819 --- /dev/null +++ b/v2/rscg_examples/Sundew.DiscriminatedUnions/src/UnionTypesDemo/UnionTypesDemo.csproj @@ -0,0 +1,21 @@ + + + + Exe + net10.0 + enable + enable + + + + true + $(BaseIntermediateOutputPath)\GX + + + + + + + + + diff --git a/v2/rscg_examples/Sundew.DiscriminatedUnions/video.json b/v2/rscg_examples/Sundew.DiscriminatedUnions/video.json new file mode 100644 index 000000000..0284d5bfb --- /dev/null +++ b/v2/rscg_examples/Sundew.DiscriminatedUnions/video.json @@ -0,0 +1,39 @@ +{ + "scriptName": "Sundew.DiscriminatedUnions", + "steps": +[ + {"typeStep":"exec","arg":"clipchamp.exe launch"}, + {"typeStep":"text","arg": "Welcome to Roslyn Examples"}, + {"typeStep":"text","arg":"If you want to see more examples , see List Of RSCG"}, + {"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/List-of-RSCG"}, + {"typeStep":"text","arg": "My name is Andrei Ignat and I am deeply fond of Roslyn Source Code Generator. "}, + +{"typeStep":"text","arg": "Today I will present Sundew.DiscriminatedUnions . Generate tagged union ."}, +{"typeStep":"browser","arg":"https://www.nuget.org/packages/Sundew.DiscriminatedUnions/"}, +{"typeStep":"text","arg": "The whole example is here"}, +{"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/Sundew.DiscriminatedUnions"}, +{"typeStep":"text","arg": "You can download the code from here"}, +{"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/Sundew.DiscriminatedUnions#download-example-net--c-"}, +{"typeStep":"text","arg":"Here is the code downloaded "}, +{"typeStep":"exec","arg":"explorer.exe /select,D:\\gth\\RSCG_Examples\\v2\\rscg_examples\\Sundew.DiscriminatedUnions\\src\\UnionTypesDemo.sln"}, +{"typeStep":"text","arg": "So , let's start the project with Visual Studio Code "}, +{"typeStep":"stepvscode","arg": "-n D:\\gth\\RSCG_Examples\\v2\\rscg_examples\\Sundew.DiscriminatedUnions\\src"}, + +{"typeStep":"text","arg": "To use it ,you will put the Nuget Sundew.DiscriminatedUnions into the csproj "}, + +{"typeStep":"stepvscode","arg": "-r -g D:\\gth\\RSCG_Examples\\v2\\rscg_examples\\Sundew.DiscriminatedUnions\\src\\UnionTypesDemo\\UnionTypesDemo.csproj"}, + +{"typeStep":"text","arg": "And now I will show you an example of using Sundew.DiscriminatedUnions"}, + +{"typeStep":"hide","arg": "now execute the tour in VSCode"}, +{"typeStep":"tour", "arg": "src/.tours/"}, +{"typeStep":"text","arg":" And I will execute the project"}, +{"typeStep":"showproj", "arg":"UnionTypesDemo.csproj"}, +{"typeStep":"text","arg":" This concludes the project"}, +{"typeStep":"waitseconds","arg":"30"}, +{"typeStep":"text","arg": "Remember, you can download the code from here"}, +{"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/Sundew.DiscriminatedUnions#download-example-net--c-", +SpeakTest=" "}, +{"typeStep":"waitseconds","arg":"30"}, +] +} diff --git a/v2/rscg_examples_site/docs/Authors/Kim_Hugener_Ohlsen.md b/v2/rscg_examples_site/docs/Authors/Kim_Hugener_Ohlsen.md new file mode 100644 index 000000000..88921ce4f --- /dev/null +++ b/v2/rscg_examples_site/docs/Authors/Kim_Hugener_Ohlsen.md @@ -0,0 +1,7 @@ +# Author : Kim Hugener Ohlsen + +Number RSCG: 1 + + + 1 [Sundew.DiscriminatedUnions](/docs/Sundew.DiscriminatedUnions) [![Nuget](https://img.shields.io/nuget/dt/Sundew.DiscriminatedUnions?label=Sundew.DiscriminatedUnions)](https://www.nuget.org/packages/Sundew.DiscriminatedUnions/) ![GitHub Repo stars](https://img.shields.io/github/stars/sundews/Sundew.DiscriminatedUnions?style=social) 2026-02-14 + diff --git a/v2/rscg_examples_site/docs/Categories/FunctionalProgramming.md b/v2/rscg_examples_site/docs/Categories/FunctionalProgramming.md index 4e83f5f8a..05ad2a145 100644 --- a/v2/rscg_examples_site/docs/Categories/FunctionalProgramming.md +++ b/v2/rscg_examples_site/docs/Categories/FunctionalProgramming.md @@ -1,6 +1,6 @@

FunctionalProgramming

-Number RSCG: 16 +Number RSCG: 17 1 [cachesourcegenerator](/docs/cachesourcegenerator) [![Nuget](https://img.shields.io/nuget/dt/cachesourcegenerator?label=cachesourcegenerator)](https://www.nuget.org/packages/cachesourcegenerator/) ![GitHub Repo stars](https://img.shields.io/github/stars/jeppevammenkristensen/cachesourcegenerator?style=social) 2024-02-14 @@ -28,9 +28,11 @@ Number RSCG: 16 13 [Sera.Union](/docs/Sera.Union) [![Nuget](https://img.shields.io/nuget/dt/Sera.Union?label=Sera.Union)](https://www.nuget.org/packages/Sera.Union/) ![GitHub Repo stars](https://img.shields.io/github/stars/sera-net/Sera.Union?style=social) 2024-08-26 - 14 [TypeUtilities](/docs/TypeUtilities) [![Nuget](https://img.shields.io/nuget/dt/TypeUtilities?label=TypeUtilities)](https://www.nuget.org/packages/TypeUtilities/) ![GitHub Repo stars](https://img.shields.io/github/stars/DragonsLord/TypeUtilities?style=social) 2024-03-05 + 14 [Sundew.DiscriminatedUnions](/docs/Sundew.DiscriminatedUnions) [![Nuget](https://img.shields.io/nuget/dt/Sundew.DiscriminatedUnions?label=Sundew.DiscriminatedUnions)](https://www.nuget.org/packages/Sundew.DiscriminatedUnions/) ![GitHub Repo stars](https://img.shields.io/github/stars/sundews/Sundew.DiscriminatedUnions?style=social) 2026-02-14 - 15 [UnionGen](/docs/UnionGen) [![Nuget](https://img.shields.io/nuget/dt/UnionGen?label=UnionGen)](https://www.nuget.org/packages/UnionGen/) ![GitHub Repo stars](https://img.shields.io/github/stars/markushaslinger/union_source_generator?style=social) 2024-04-05 + 15 [TypeUtilities](/docs/TypeUtilities) [![Nuget](https://img.shields.io/nuget/dt/TypeUtilities?label=TypeUtilities)](https://www.nuget.org/packages/TypeUtilities/) ![GitHub Repo stars](https://img.shields.io/github/stars/DragonsLord/TypeUtilities?style=social) 2024-03-05 - 16 [UnionsGenerator](/docs/UnionsGenerator) [![Nuget](https://img.shields.io/nuget/dt/RhoMicro.CodeAnalysis.UnionsGenerator?label=RhoMicro.CodeAnalysis.UnionsGenerator)](https://www.nuget.org/packages/RhoMicro.CodeAnalysis.UnionsGenerator) ![GitHub Repo stars](https://img.shields.io/github/stars/PaulBraetz/RhoMicro.CodeAnalysis?style=social) 2024-02-18 + 16 [UnionGen](/docs/UnionGen) [![Nuget](https://img.shields.io/nuget/dt/UnionGen?label=UnionGen)](https://www.nuget.org/packages/UnionGen/) ![GitHub Repo stars](https://img.shields.io/github/stars/markushaslinger/union_source_generator?style=social) 2024-04-05 + + 17 [UnionsGenerator](/docs/UnionsGenerator) [![Nuget](https://img.shields.io/nuget/dt/RhoMicro.CodeAnalysis.UnionsGenerator?label=RhoMicro.CodeAnalysis.UnionsGenerator)](https://www.nuget.org/packages/RhoMicro.CodeAnalysis.UnionsGenerator) ![GitHub Repo stars](https://img.shields.io/github/stars/PaulBraetz/RhoMicro.CodeAnalysis?style=social) 2024-02-18 \ No newline at end of file diff --git a/v2/rscg_examples_site/docs/Categories/_PrimitiveFunctionalProgramming.mdx b/v2/rscg_examples_site/docs/Categories/_PrimitiveFunctionalProgramming.mdx index ba68dbd1f..b61057fce 100644 --- a/v2/rscg_examples_site/docs/Categories/_PrimitiveFunctionalProgramming.mdx +++ b/v2/rscg_examples_site/docs/Categories/_PrimitiveFunctionalProgramming.mdx @@ -26,11 +26,13 @@ 13 [Sera.Union](/docs/Sera.Union) [![Nuget](https://img.shields.io/nuget/dt/Sera.Union?label=Sera.Union)](https://www.nuget.org/packages/Sera.Union/) ![GitHub Repo stars](https://img.shields.io/github/stars/sera-net/Sera.Union?style=social) 2024-08-26 - 14 [TypeUtilities](/docs/TypeUtilities) [![Nuget](https://img.shields.io/nuget/dt/TypeUtilities?label=TypeUtilities)](https://www.nuget.org/packages/TypeUtilities/) ![GitHub Repo stars](https://img.shields.io/github/stars/DragonsLord/TypeUtilities?style=social) 2024-03-05 + 14 [Sundew.DiscriminatedUnions](/docs/Sundew.DiscriminatedUnions) [![Nuget](https://img.shields.io/nuget/dt/Sundew.DiscriminatedUnions?label=Sundew.DiscriminatedUnions)](https://www.nuget.org/packages/Sundew.DiscriminatedUnions/) ![GitHub Repo stars](https://img.shields.io/github/stars/sundews/Sundew.DiscriminatedUnions?style=social) 2026-02-14 - 15 [UnionGen](/docs/UnionGen) [![Nuget](https://img.shields.io/nuget/dt/UnionGen?label=UnionGen)](https://www.nuget.org/packages/UnionGen/) ![GitHub Repo stars](https://img.shields.io/github/stars/markushaslinger/union_source_generator?style=social) 2024-04-05 + 15 [TypeUtilities](/docs/TypeUtilities) [![Nuget](https://img.shields.io/nuget/dt/TypeUtilities?label=TypeUtilities)](https://www.nuget.org/packages/TypeUtilities/) ![GitHub Repo stars](https://img.shields.io/github/stars/DragonsLord/TypeUtilities?style=social) 2024-03-05 - 16 [UnionsGenerator](/docs/UnionsGenerator) [![Nuget](https://img.shields.io/nuget/dt/RhoMicro.CodeAnalysis.UnionsGenerator?label=RhoMicro.CodeAnalysis.UnionsGenerator)](https://www.nuget.org/packages/RhoMicro.CodeAnalysis.UnionsGenerator) ![GitHub Repo stars](https://img.shields.io/github/stars/PaulBraetz/RhoMicro.CodeAnalysis?style=social) 2024-02-18 + 16 [UnionGen](/docs/UnionGen) [![Nuget](https://img.shields.io/nuget/dt/UnionGen?label=UnionGen)](https://www.nuget.org/packages/UnionGen/) ![GitHub Repo stars](https://img.shields.io/github/stars/markushaslinger/union_source_generator?style=social) 2024-04-05 + + 17 [UnionsGenerator](/docs/UnionsGenerator) [![Nuget](https://img.shields.io/nuget/dt/RhoMicro.CodeAnalysis.UnionsGenerator?label=RhoMicro.CodeAnalysis.UnionsGenerator)](https://www.nuget.org/packages/RhoMicro.CodeAnalysis.UnionsGenerator) ![GitHub Repo stars](https://img.shields.io/github/stars/PaulBraetz/RhoMicro.CodeAnalysis?style=social) 2024-02-18 ### See category diff --git a/v2/rscg_examples_site/docs/RSCG-Examples/Sundew.DiscriminatedUnions.md b/v2/rscg_examples_site/docs/RSCG-Examples/Sundew.DiscriminatedUnions.md new file mode 100644 index 000000000..6d575878a --- /dev/null +++ b/v2/rscg_examples_site/docs/RSCG-Examples/Sundew.DiscriminatedUnions.md @@ -0,0 +1,433 @@ +--- +sidebar_position: 2560 +title: 256 - Sundew.DiscriminatedUnions +description: Generate tagged union +slug: /Sundew.DiscriminatedUnions +--- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import TOCInline from '@theme/TOCInline'; +import SameCategory from '../Categories/_PrimitiveFunctionalProgramming.mdx'; + +# Sundew.DiscriminatedUnions by Kim Hugener Ohlsen + + + + +## NuGet / site data +[![Nuget](https://img.shields.io/nuget/dt/Sundew.DiscriminatedUnions?label=Sundew.DiscriminatedUnions)](https://www.nuget.org/packages/Sundew.DiscriminatedUnions/) +[![GitHub last commit](https://img.shields.io/github/last-commit/sundews/Sundew.DiscriminatedUnions?label=updated)](https://github.com/sundews/Sundew.DiscriminatedUnions) +![GitHub Repo stars](https://img.shields.io/github/stars/sundews/Sundew.DiscriminatedUnions?style=social) + +## Details + +### Info +:::info + +Name: **Sundew.DiscriminatedUnions** + + + +Author: Kim Hugener Ohlsen + +NuGet: +*https://www.nuget.org/packages/Sundew.DiscriminatedUnions/* + + +You can find more details at https://github.com/sundews/Sundew.DiscriminatedUnions + +Source: https://github.com/sundews/Sundew.DiscriminatedUnions + +::: + +### Author +:::note +Kim Hugener Ohlsen +![Alt text](https://github.com/sundews.png) +::: + +## Original Readme +:::note + +### Discriminated Unions + +Sundew.DiscriminatedUnions implement discriminated unions for C#, until a future version of C# provides it out of the box. +The idea is that this package can be deleted once unions are supported in C#, without requiring changes to switch expressions and statements. + +In addition, the project supports dimensional unions through default interface methods (traits). +A dimensional union is a union where cases can be reused in any number of unions, by supporting interface unions through the possibility of implementing multiple interface and default interface members. + +###### How it works +A Roslyn analyzer asserts and report errors in case switch statements or switch expression do not handle all cases. +C# 8 and 9 already comes with great pattern matching support for evaluation. + +In order that the inheritance hierarchy remain closed (All cases in the same assembly), an analyzer ensures that unions are not derived from in referencing assemblies. +Similarly all case classes should be sealed. + +Create a union by inheriting from an abstract base (record) class (or interface) marked with the DiscriminatedUnion attribute to build various cases. +Either specify the partial keyword to the union for a source generator to implement factory methods or use the codefix PDU0001 to generate them. + +###### Sample +######### Defining a union +```csharp +[Sundew.DiscriminatedUnions.DiscriminatedUnion] +public abstract partial record Result +{ + public sealed partial record Success : Result; + + public sealed partial record Warning(string Message) : Result; + + public sealed partial record Error(int Code) : Result; +} +``` +Alternatively, a union can be defined with unnested case classes and interfaces, allowing the possibility of creating dimensional unions (see below). + +######### Evaluation +```csharp +var message = result switch +{ + Result.Error \{ Code: > 70 \} error => $"High Error code: {error.Code}", + Result.Error error => $"Error code: {error.Code}", + Result.Warning \{ Message: "Tough warning" \} => "Not good", + Result.Warning warning => warning.Message, + Result.Success => "Great", +}; +``` + +######### Dimensional unions +To support dimensional unions, unnested cases help because the cases are no longer defined inside a union. However, for this to work the unions are required to declare a factory method named exactly like the case type and that has the CaseType attribute specifying the actual type. +Since version 3, factory methods are generated when the union is declared partial. Alternatively, a code fix (PDU0001) is available to generate the factory methods. + +```csharp +[Sundew.DiscriminatedUnions.DiscriminatedUnion] +public partial interface IExpression; + +[Sundew.DiscriminatedUnions.DiscriminatedUnion] +public partial interface IArithmeticExpression : IExpression; + +[Sundew.DiscriminatedUnions.DiscriminatedUnion] +public partial interface ICommutativeExpression : IArithmeticExpression; + +public sealed partial record AdditionExpression(IExpression Lhs, IExpression Rhs) : ICommutativeExpression; + +public sealed partial record SubtractionExpression(IExpression Lhs, IExpression Rhs) : IArithmeticExpression; + +public sealed partial record MultiplicationExpression(IExpression Lhs, IExpression Rhs) : ICommutativeExpression; + +public sealed partial record DivisionExpression(IExpression Lhs, IExpression Rhs) : IArithmeticExpression; + +public sealed partial record ValueExpression(int Value) : IExpression; +``` + +########## Evaluating dimensional unions +With dimensional unions it is possible to handle all cases using a sub union. +As seen in the example below, handling the ArithmeticExpression covers Addition-, Subtraction-, Multiplication- and DivisionExpression. +Typically one would dispatch these to a method handling ArithmeticExpression and where handling all cases would be checked, but it is not required. +This makes it convienient to separate handling logic in smaller chucks of code. + +```csharp +public int Evaluate(Expression expression) +{ + return expression switch + { + ArithmeticExpression arithmeticExpression => Evaluate(arithmeticExpression), + ValueExpression valueExpression => valueExpression.Value, + }; +} + +public int Evaluate(ArithmeticExpression arithmeticExpression) +{ + return arithmeticExpression switch + { + AdditionExpression additionExpression => Evaluate(additionExpression.Lhs) + Evaluate(additionExpression.Rhs), + SubtractionExpression subtractionExpression => Evaluate(subtractionExpression.Lhs) - Evaluate(subtractionExpression.Rhs), + MultiplicationExpression multiplicationExpression => Evaluate(multiplicationExpression.Lhs) * Evaluate(multiplicationExpression.Rhs), + DivisionExpression divisionExpression => Evaluate(divisionExpression.Lhs) / Evaluate(divisionExpression.Rhs), + }; +} +``` + +########## Enum evaluation +As of version 5.1, regular enums can also use the DiscriminatedUnion attribute causing the analyzer to exhaustively check switch statements and expressions. + +###### Generator features +As mentioned a source generator is automatically activated for generating factory methods when the partial keyword is specified. +In addition, the DiscriminatedUnion attribute can specify a flags enum (GeneratorFeatures) to control additional code generation. + +* Segregate - Generates an extension method for IEnumerable\ that segregates all items into buckets of the different result. + +###### Supported diagnostics: +| Diagnostic Id | Description | Code Fix | +| ------------- | ------------------------------------------------------------------------------------------------------------------------- | :------: | +| SDU0001 | Switch does not handled all cases | yes | +| SDU0002 | Switch should not handle default case | yes | +| SDU0003 | Switch has unreachable null case | yes | +| SDU0004 | Class unions must be abstract | yes | +| SDU0005 | Only unions can extended other unions | no | +| SDU0006 | Unions cannot be extended outside their assembly | no | +| SDU0007 | Cases must be declared in the same assembly as their unions | no | +| SDU0008 | Cases should be sealed | yes | +| SDU0009 | Unnested cases should have factory method | PDU0001 | +| SDU0010 | Factory method should have correct CaseTypeAttribute | yes | +| SDU0011 | Reported when a case is implemented by throwing NotImplementedException, because CodeCleanup may siliently 'fix' SDU0001. | yes | +| SDU0012 | Reported when a case contains type parameters that are not in the union type parameter list. | yes | +| PDU0001 | Make union/case partial for code generator | yes | +| PDU0002 | Populate union factory methods | yes | +| SDU9999 | Switch should throw in default case | no | +| GDU0001 | Discriminated union declaration could not be found | no | + +###### Issues/Todos +* Switch appears with red squiggly lines in VS: https://github.com/dotnet/roslyn/issues/57041 +* Nullability is falsely evaluated when the switch hints null is possible: https://github.com/dotnet/roslyn/issues/57042 + +::: + +### About +:::note + +Generate tagged union + + +::: + +## How to use + +### Example (source csproj, source files) + + + + + +This is the CSharp Project that references **Sundew.DiscriminatedUnions** +```xml showLineNumbers {16} + + + + Exe + net10.0 + enable + enable + + + + true + $(BaseIntermediateOutputPath)\GX + + + + + + + + + + +``` + + + + + + This is the use of **Sundew.DiscriminatedUnions** in *Program.cs* + +```csharp showLineNumbers +using UnionTypesDemo; + +Console.WriteLine("Save or not"); +ResultSave data = SaveToDatabase.Save(0); +var message= data switch +{ + ResultSave.Ok ok => $"Saved {ok.i}", + ResultSave.NotFound => "Not found", +}; +Console.WriteLine(message); +data = SaveToDatabase.Save(1); +message = data switch +{ + ResultSave.Ok ok => $"Saved {ok.i}", + ResultSave.NotFound => "Not found", +}; +Console.WriteLine(message); + +``` + + + + + This is the use of **Sundew.DiscriminatedUnions** in *ResultSave.cs* + +```csharp showLineNumbers + +using Sundew.DiscriminatedUnions; + +namespace UnionTypesDemo; + + +[DiscriminatedUnion] +public abstract partial record ResultSave +{ + + public sealed partial record Ok(int i) : ResultSave; + + public sealed partial record NotFound():ResultSave ; + +} + + +``` + + + + + This is the use of **Sundew.DiscriminatedUnions** in *SaveToDatabase.cs* + +```csharp showLineNumbers +namespace UnionTypesDemo; + +public class SaveToDatabase +{ + public static ResultSave Save(int i) + { + + if (i == 0) + { + return ResultSave._NotFound; + } + return ResultSave._Ok(i); + } +} + + + +``` + + + + +### Generated Files + +Those are taken from $(BaseIntermediateOutputPath)\GX + + + + +```csharp showLineNumbers +#nullable enable + +namespace UnionTypesDemo +{ +#pragma warning disable SA1601 + [global::System.Diagnostics.DebuggerNonUserCode] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Sundew.DiscriminateUnions.Generator", "6.0.0.0")] + public partial record ResultSave : global::Sundew.DiscriminatedUnions.IDiscriminatedUnion +#pragma warning restore SA1601 + { + /// + /// Gets the NotFound case. + /// + /// The NotFound. + [Sundew.DiscriminatedUnions.CaseType(typeof(global::UnionTypesDemo.ResultSave.NotFound))] + public static global::UnionTypesDemo.ResultSave _NotFound \{ get; } + = new global::UnionTypesDemo.ResultSave.NotFound(); + + /// + /// Factory method for the Ok case. + /// + /// The i. + /// A new Ok. + [Sundew.DiscriminatedUnions.CaseType(typeof(global::UnionTypesDemo.ResultSave.Ok))] + public static global::UnionTypesDemo.ResultSave _Ok(int i) + => new global::UnionTypesDemo.ResultSave.Ok(i); + + /// + /// Gets all cases in the union. + /// + /// A readonly list of types. + public static global::System.Collections.Generic.IReadOnlyList Cases \{ get; } + = new global::System.Type[] \{ typeof(global::UnionTypesDemo.ResultSave.NotFound), typeof(global::UnionTypesDemo.ResultSave.Ok) }; + } +} + +``` + + + + +```csharp showLineNumbers +#nullable enable + +namespace UnionTypesDemo +{ + public partial record ResultSave + { +#pragma warning disable SA1601 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Sundew.DiscriminateUnions.Generator", "6.0.0.0")] + public partial record NotFound +#pragma warning restore SA1601 + { + /// + /// Gets all cases in the union. + /// + /// A readonly list of types. + public new static global::System.Collections.Generic.IReadOnlyList Cases \{ get; } + = new global::System.Type[] \{ typeof(global::UnionTypesDemo.ResultSave.NotFound) }; + } + } +} + +``` + + + + +```csharp showLineNumbers +#nullable enable + +namespace UnionTypesDemo +{ + public partial record ResultSave + { +#pragma warning disable SA1601 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Sundew.DiscriminateUnions.Generator", "6.0.0.0")] + public partial record Ok +#pragma warning restore SA1601 + { + /// + /// Gets all cases in the union. + /// + /// A readonly list of types. + public new static global::System.Collections.Generic.IReadOnlyList Cases \{ get; } + = new global::System.Type[] \{ typeof(global::UnionTypesDemo.ResultSave.Ok) }; + } + } +} + +``` + + + + +## Useful + +### Download Example (.NET C#) + +:::tip + +[Download Example project Sundew.DiscriminatedUnions ](/sources/Sundew.DiscriminatedUnions.zip) + +::: + + +### Share Sundew.DiscriminatedUnions + + + +https://ignatandrei.github.io/RSCG_Examples/v2/docs/Sundew.DiscriminatedUnions + + + diff --git a/v2/rscg_examples_site/docs/RSCG-Examples/index.md b/v2/rscg_examples_site/docs/RSCG-Examples/index.md index dac55d475..c7b8c6b00 100644 --- a/v2/rscg_examples_site/docs/RSCG-Examples/index.md +++ b/v2/rscg_examples_site/docs/RSCG-Examples/index.md @@ -1,7 +1,7 @@ --- sidebar_position: 30 -title: 255 RSCG list by category -description: 255 RSCG list by category +title: 256 RSCG list by category +description: 256 RSCG list by category slug: /rscg-examples --- @@ -954,7 +954,7 @@ import DocCardList from '@theme/DocCardList'; ## FunctionalProgramming
- Expand FunctionalProgramming =>examples:16 + Expand FunctionalProgramming =>examples:17 @@ -1035,6 +1035,11 @@ import DocCardList from '@theme/DocCardList'; [rscg_demeter](/docs/rscg_demeter) + + + +[Sundew.DiscriminatedUnions](/docs/Sundew.DiscriminatedUnions) +
@@ -1949,6 +1954,8 @@ flowchart LR; FunctionalProgramming--> rscg_demeter((rscg_demeter)) + FunctionalProgramming--> Sundew.DiscriminatedUnions((Sundew.DiscriminatedUnions)) + Hangfire--> HangfireRecurringJob((HangfireRecurringJob)) Idempotency--> RSCG_idempotency((RSCG_idempotency)) diff --git a/v2/rscg_examples_site/docs/about.md b/v2/rscg_examples_site/docs/about.md index b81a91fe8..d16c4e722 100644 --- a/v2/rscg_examples_site/docs/about.md +++ b/v2/rscg_examples_site/docs/about.md @@ -6,7 +6,7 @@ title: About ## Content You will find here code examples -of 255 Roslyn Source Code Generator (RSCG) +of 256 Roslyn Source Code Generator (RSCG) that can be useful for you. That means, you will write more elegant and concise code - even if the generators code is not always nice to look. ## Are those examples ready for production? diff --git a/v2/rscg_examples_site/docs/indexRSCG.md b/v2/rscg_examples_site/docs/indexRSCG.md index 539881405..72222025b 100644 --- a/v2/rscg_examples_site/docs/indexRSCG.md +++ b/v2/rscg_examples_site/docs/indexRSCG.md @@ -7,9 +7,9 @@ slug: /List-of-RSCG import useBaseUrl from '@docusaurus/useBaseUrl'; -## 255 RSCG with examples in descending chronological order +## 256 RSCG with examples in descending chronological order -This is the list of 255 ( 16 from Microsoft) RSCG with examples +This is the list of 256 ( 16 from Microsoft) RSCG with examples [See by category](/docs/rscg-examples) [See as json](/exports/RSCG.json) [See as Excel](/exports/RSCG.xlsx) @@ -20,6 +20,7 @@ This is the list of 255 ( 16 from Microsoft) RSCG with examples | No | Name | Date | Category | | --------- | ----- | ---- | -------- | +|256| [Sundew.DiscriminatedUnions by Kim Hugener Ohlsen ](/docs/Sundew.DiscriminatedUnions)|2026-02-14 => 14 February 2026 | [FunctionalProgramming](/docs/Categories/FunctionalProgramming) | |255| [KnockOff by Keith Voels ](/docs/KnockOff)|2026-02-13 => 13 February 2026 | [Tests](/docs/Categories/Tests) | |254| [ErrorOrX by Alexander Nachtmanns ](/docs/ErrorOrX)|2026-02-02 => 02 February 2026 | [API](/docs/Categories/API) | |253| [FastCloner by Matěj Štágl ](/docs/FastCloner)|2026-02-01 => 01 February 2026 | [Clone](/docs/Categories/Clone) | diff --git a/v2/rscg_examples_site/src/components/HomepageFeatures/index.js b/v2/rscg_examples_site/src/components/HomepageFeatures/index.js index a4510b61c..b7a13c155 100644 --- a/v2/rscg_examples_site/src/components/HomepageFeatures/index.js +++ b/v2/rscg_examples_site/src/components/HomepageFeatures/index.js @@ -4,7 +4,7 @@ import styles from './styles.module.css'; const FeatureList = [ { -title: '255 Examples (16 from MSFT)', +title: '256 Examples (16 from MSFT)', Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default, description: ( <> diff --git a/v2/rscg_examples_site/static/exports/RSCG.json b/v2/rscg_examples_site/static/exports/RSCG.json index 39a8a25cc..6ee1a8f19 100644 --- a/v2/rscg_examples_site/static/exports/RSCG.json +++ b/v2/rscg_examples_site/static/exports/RSCG.json @@ -2041,6 +2041,14 @@ "Source": "https://github.com/NeatooDotNet/KnockOff", "Category": "Tests", "AddedOn": "2026-02-13T00:00:00" + }, + { + "Name": "Sundew.DiscriminatedUnions", + "Link": "https://ignatandrei.github.io/RSCG_Examples/v2/docs/Sundew.DiscriminatedUnions", + "NuGet": "https://www.nuget.org/packages/Sundew.DiscriminatedUnions/", + "Source": "https://github.com/sundews/Sundew.DiscriminatedUnions", + "Category": "FunctionalProgramming", + "AddedOn": "2026-02-14T00:00:00" } ] } \ No newline at end of file diff --git a/v2/rscg_examples_site/static/exports/RSCG.xlsx b/v2/rscg_examples_site/static/exports/RSCG.xlsx index 71ca47d9d..5b5c8c091 100644 Binary files a/v2/rscg_examples_site/static/exports/RSCG.xlsx and b/v2/rscg_examples_site/static/exports/RSCG.xlsx differ diff --git a/v2/rscg_examples_site/static/sources/Sundew.DiscriminatedUnions.zip b/v2/rscg_examples_site/static/sources/Sundew.DiscriminatedUnions.zip new file mode 100644 index 000000000..66f6f2f47 Binary files /dev/null and b/v2/rscg_examples_site/static/sources/Sundew.DiscriminatedUnions.zip differ