Skip to content

Commit b1e73c8

Browse files
committed
#7 updated relevant documentation
1 parent 8263c42 commit b1e73c8

4 files changed

Lines changed: 138 additions & 2 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ A library that automatically adds support for object deconstruction in C#.
66

77
The idea started with [this tweet](https://twitter.com/buhakmeh/status/1462106117564207104) - specifically, [this reply](https://twitter.com/dave_peixoto/status/1462181358248374278). I thought...how automatic can I make object deconstruction in C#? That's what this source generator is all about.
88

9-
Read [the design document](docs/Design.md) for further details.
9+
Read [the overview document](docs/Overview.md) for further details.

changelog.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## [1.0.0] - Not Released Yest
8+
## [1.0.0] - 2022.11.25
99

1010
### Added
1111
- Generated code now uses fully-qualified named (issue [#5](https://github.com/JasonBock/AutoDeconstruct/issues/5))
1212
- Records are now considered for `Deconstruct()` generation (issue [#4](https://github.com/JasonBock/AutoDeconstruct/issues/4))
1313
- Putting `[NoAutoDeconstruct]` on a type will signal AutoDeconstruct not to generate a `Deconstruct()` method (issue [#6](https://github.com/JasonBock/AutoDeconstruct/issues/6))
1414
- All parameter names now have `@` in front to eliminate any potential keyword conflicts (issue [#9](https://github.com/JasonBock/AutoDeconstruct/issues/9))
15+
16+
### Changed
17+
- Updated documentation (issue [#7](https://github.com/JasonBock/AutoDeconstruct/issues/7))
1518
- Generated code is now stored in one file (issue [#2](https://github.com/JasonBock/AutoDeconstruct/issues/2))
1619

1720
### Fixed

docs/Overview.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# Table of Contents
2+
- [What is a Deconstructor?](#what-is-a-deconstructor?)
3+
- [AutoDeconstruct Features](#autodeconstruct-rationale)
4+
5+
## What is a Deconstructor?
6+
7+
Object deconstruction was added in C# 7.0. The documentation is [here](https://github.com/dotnet/roslyn/blob/main/docs/features/deconstruction.md), and there's another article [here](https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/functional/deconstruct#user-defined-types). Basically, a deconstructor can be defined on either a type or as an extension method. In both cases, it has to be named "Deconstruct", it has to return `void`, and all of its parameters must be `out` parameters (the exception is with the extension method, where the first parameter is the object being extended). Furthermore, you can overload `Deconstruct` methods, but all `Deconstruct` methods must have a unique number of `out` parameters. Here are two examples:
8+
9+
```csharp
10+
using System;
11+
12+
public sealed class Customer
13+
{
14+
public Customer(Guid id, string name) =>
15+
(this.Id, this.Name) = (id, name);
16+
17+
public void Deconstruct(out Guid id, out string name) =>
18+
(id, name) = (this.Id, this.Name);
19+
20+
public Guid Id { get; }
21+
public string Name { get; }
22+
}
23+
24+
var customer = new Customer(Guid.NewGuid(), "Jason");
25+
var (id, name) = customer;
26+
27+
public struct Point
28+
{
29+
public Point(int x, int y) =>
30+
(this.X, this.Y) = (x, y);
31+
32+
public int X { get; }
33+
public int Y { get; }
34+
}
35+
36+
public static class PointExtensions
37+
{
38+
public static void Deconstruct(this Point self, out int x, out int y) =>
39+
(x, y) = (self.X, self.Y);
40+
}
41+
42+
var point = new Point(2, 3);
43+
var (x, y) = point;
44+
```
45+
46+
## AutoDeconstruct Features
47+
48+
AutoDeconstruct finds all type and method definitions, and it'll look to see if the type has any `Deconstruct` methods, either as instance or extension methods. If none exist, then AutoDeconstruct looks to see how many public, readable, instance properties exist. If there's at least 1, the library generates a `Deconstruct` extension method in a static class defined in the same namespace as the target type. For example, if we have our `Point` type defined like this:
49+
50+
```csharp
51+
namespace Maths.Geometry;
52+
53+
public struct Point
54+
{
55+
public Point(int x, int y) =>
56+
(this.X, this.Y) = (x, y);
57+
58+
public int X { get; }
59+
public int Y { get; }
60+
}
61+
```
62+
63+
Then the library generates this:
64+
65+
```csharp
66+
#nullable enable
67+
68+
namespace Maths.Geometry
69+
{
70+
public static partial class PointExtensions
71+
{
72+
public static void Deconstruct(this global::Maths.Geometry.Point @self, out int @x, out int @y) =>
73+
(@x, @y) = (@self.X, @self.Y);
74+
}
75+
}
76+
```
77+
78+
If the target type is a reference type, a null check will be generated. Furthermore, the `Deconstruct` extension method will also be created if a `Deconstruct` doesn't exist with the number of properties found. For example, let's say we have this:
79+
80+
```csharp
81+
namespace Models;
82+
83+
public sealed class Person
84+
{
85+
public void Deconstruct(out Guid id) =>
86+
id = this.Id;
87+
88+
public uint Age { get; init; }
89+
public Guid Id { get; init; }
90+
public string Name { get; init; }
91+
}
92+
93+
public static class PersonExtensions
94+
{
95+
public static void Deconstruct(this Person self, out Guid id, out string name) =>
96+
(id, name) = (self.Id, self.Name);
97+
}
98+
```
99+
100+
AutoDeconstruct would see that there are three properties that could be used for a generated `Deconstruct`. The two `Deconstruct` methods that exist have one and two `out` parameters, so it will generate one that has all three properties as `out` parameters:
101+
102+
```csharp
103+
#nullable enable
104+
105+
namespace Models
106+
{
107+
public static partial class PersonExtensions
108+
{
109+
public static void Deconstruct(this global::Models.Person @self, out global::System.Guid @id, out string @name, out uint @age)
110+
{
111+
global::System.ArgumentNullException.ThrowIfNull(@self);
112+
(@id, @name, @age) = (@self.Id, @self.Name, @self.Age);
113+
}
114+
}
115+
}
116+
```
117+
118+
While AutoDeconstruct will do a complete search for types to generate `Deconstruct` methods, a user may want to opt out of this search for specific types. Adding the `[NoAutoDeconstruct]` attribute to a type will tell AutoDeconstrct to ignore it:
119+
120+
```csharp
121+
namespace AutoDeconstruct;
122+
namespace Models;
123+
124+
[NoAutoDeconstruct]
125+
public sealed class Person
126+
{
127+
public uint Age { get; init; }
128+
public Guid Id { get; init; }
129+
public string Name { get; init; }
130+
}
131+
```
132+
133+
In this case, AutoDeconstruct will not generate a `Deconstruct` method for `Person`.
File renamed without changes.

0 commit comments

Comments
 (0)