|
| 1 | +## Prerequisites |
| 2 | +1. Install the latest stable [.NET SDK](https://dotnet.microsoft.com/en-us/download). |
| 3 | +2. Install .NET MAUI workloads (we recommend using Visual Studio installer). |
| 4 | + |
| 5 | +## Setting Up GitHub Copilot |
| 6 | +1. Ensure you have GitHub Copilot installed and enabled in Visual Studio. |
| 7 | +2. Familiarize yourself with the basic usage of GitHub Copilot by reviewing the (official documentation)[https://docs.github.com/en/copilot]. |
| 8 | + |
| 9 | +## Writing Code with GitHub Copilot |
| 10 | +### General Guidelines |
| 11 | +* Use GitHub Copilot to assist with code completion, documentation, and generating boilerplate code. |
| 12 | +* Always review and test the code suggested by GitHub Copilot to ensure it meets the project's standards and requirements. |
| 13 | + |
| 14 | +### Specific to .NET MAUI |
| 15 | +* Ensure that any UI components or controls are compatible with .NET MAUI. |
| 16 | +* Avoid using Xamarin.Forms-specific code unless there is a direct .NET MAUI equivalent. |
| 17 | +* Follow the project's coding style and best practices as outlined in the (contributing)[https://github.com/CommunityToolkit/Maui/blob/main/CONTRIBUTING.md] document. |
| 18 | + |
| 19 | +## Best Practices |
| 20 | +* Use **Trace.WriteLine()** for debug logging instead of **Debug.WriteLine()**. |
| 21 | +* Include a **CancellationToken** as a parameter for methods returning **Task** or **ValueTask**. |
| 22 | +* Use **is** for null checking and type checking. |
| 23 | +* Use file-scoped namespaces to reduce code verbosity. |
| 24 | +* Avoid using the **!** null forgiving operator. |
| 25 | +* Follow naming conventions for enums and property names. |
| 26 | + |
| 27 | +### Debug Logging |
| 28 | +* Always use `Trace.WriteLine()` instead of `Debug.WriteLine` for debug logging because `Debug.WriteLine` is removed by the compiler in Release builds |
| 29 | + |
| 30 | +### Methods Returning Task and ValueTask |
| 31 | +* Always include a `CancellationToken` as a parameter to every method returning `Task` or `ValueTask` |
| 32 | +* If the method is public, provide a the default value for the `CancellationToken` (e.g. `CancellationToken token = default`) |
| 33 | +* If the method is not public, do not provide a default value for the `CancellationToken` |
| 34 | +* If the method is used outside of a .net MAUI control, Use `CancellationToken.ThrowIfCancellationRequested()` to verify the `CancellationToken`, as it is not possible to catch exceptions in XAML. |
| 35 | + |
| 36 | +### Enums |
| 37 | +* Always use `Unknown` at index 0 for return types that may have a value that is not known |
| 38 | +* Always use `Default` at index 0 for option types that can use the system default option |
| 39 | +* Follow naming guidelines for tense... `SensorSpeed` not `SensorSpeeds` |
| 40 | +* Assign values (0,1,2,3) for all enums, if not marked with a `Flags` attribute. This is to ensure that the enum can be serialized and deserialized correctly across platforms. |
| 41 | + |
| 42 | +### Property Names |
| 43 | +* Include units only if one of the platforms includes it in their implementation. For instance HeadingMagneticNorth implies degrees on all platforms, but PressureInHectopascals is needed since platforms don't provide a consistent API for this. |
| 44 | + |
| 45 | +### Units |
| 46 | +* Use the standard units and most well accepted units when possible. For instance Hectopascals are used on UWP/Android and iOS uses Kilopascals so we have chosen Hectopascals. |
| 47 | + |
| 48 | +### Pattern matching |
| 49 | +#### Null checking |
| 50 | +* Prefer using `is` when checking for null instead of `==`. |
| 51 | + |
| 52 | +e.g. |
| 53 | + |
| 54 | +```csharp |
| 55 | +// null |
| 56 | +if (something is null) |
| 57 | +{ |
| 58 | + |
| 59 | +} |
| 60 | + |
| 61 | +// or not null |
| 62 | +if (something is not null) |
| 63 | +{ |
| 64 | + |
| 65 | +} |
| 66 | +``` |
| 67 | + |
| 68 | +* Avoid using the `!` [null forgiving operator](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-forgiving) to avoid the unintended introduction of bugs. |
| 69 | + |
| 70 | +#### Type checking |
| 71 | +* Prefer `is` when checking for types instead of casting. |
| 72 | + |
| 73 | +e.g. |
| 74 | + |
| 75 | +```csharp |
| 76 | +if (something is Bucket bucket) |
| 77 | +{ |
| 78 | + bucket.Empty(); |
| 79 | +} |
| 80 | +``` |
| 81 | + |
| 82 | +### Use collection initializers or expressions |
| 83 | +* Use [Use collection initializers or expressions](https://learn.microsoft.com/en-gb/dotnet/fundamentals/code-analysis/style-rules/ide0028) Use collection initializers or expressions. |
| 84 | + |
| 85 | +e.g. |
| 86 | + |
| 87 | +```csharp |
| 88 | +List<int> list = [1, 2, 3]; |
| 89 | +List<int> list = []; |
| 90 | +``` |
| 91 | + |
| 92 | +### File Scoped Namespaces |
| 93 | +* Use [file scoped namespaces](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/file-scoped-namespaces) to help reduce code verbosity. |
| 94 | + |
| 95 | +e.g. |
| 96 | + |
| 97 | +```csharp |
| 98 | +namespace CommunityToolkit.Maui.Converters; |
| 99 | + |
| 100 | +using System; |
| 101 | + |
| 102 | +class BoolToObjectConverter |
| 103 | +{ |
| 104 | +} |
| 105 | +``` |
| 106 | + |
| 107 | +### Braces |
| 108 | +Please use `{ }` after `if`, `for`, `foreach`, `do`, `while`, etc. |
| 109 | + |
| 110 | +e.g. |
| 111 | + |
| 112 | +```csharp |
| 113 | +if (something is not null) |
| 114 | +{ |
| 115 | + ActOnIt(); |
| 116 | +} |
| 117 | +``` |
| 118 | + |
| 119 | +### `NotImplementedException` |
| 120 | +* Please avoid adding new code that throws a `NotImplementedException`. According to the [Microsoft Docs](https://docs.microsoft.com/dotnet/api/system.notimplementedexception), we should only "throw a `NotImplementedException` exception in properties or methods in your own types when that member is still in development and will only later be implemented in production code. In other words, a NotImplementedException exception should be synonymous with 'still in development.'" |
| 121 | +In other words, `NotImplementedException` implies that a feature is still in development, indicating that the Pull Request is incomplete. |
| 122 | + |
| 123 | +### Bug Fixes |
| 124 | +If you're looking for something to fix, please browse [open issues](https://github.com/CommunityToolkit/Maui/issues). |
| 125 | + |
| 126 | +Follow the style used by the [.NET Foundation](https://github.com/dotnet/runtime/blob/master/docs/coding-guidelines/coding-style.md), with two primary exceptions: |
| 127 | + |
| 128 | +* We do **not** use the `private` keyword as it is the default accessibility level in C#. |
| 129 | +* We will **not** use `_` or `s_` as a prefix for internal or private field names |
| 130 | +* We will use `camelCaseFieldName` for naming internal or private fields in both instance and static implementations |
| 131 | + |
| 132 | +Read and follow our [Pull Request template](https://github.com/CommunityToolkit/Maui/blob/main/.github/PULL_REQUEST_TEMPLATE.md) |
| 133 | + |
| 134 | +## Submitting Contributions |
| 135 | +1. Fork the repository and create a new branch for your changes. |
| 136 | +2. Implement your changes using GitHub Copilot as needed. |
| 137 | +3. Ensure your changes include tests, samples, and documentation. |
| 138 | +4. Open a pull request and follow the [Pull Request template](https://github.com/CommunityToolkit/Maui/blob/main/.github/PULL_REQUEST_TEMPLATE.md). |
| 139 | + |
| 140 | +## Additional Resources |
| 141 | +- (GitHub Copilot Documentation)[https://docs.github.com/en/copilot] |
| 142 | +- [.NET MAUI Documentation](https://learn.microsoft.com/en-us/dotnet/maui/) |
| 143 | + |
| 144 | +By following these guidelines, you can effectively use GitHub Copilot to contribute to the .NET MAUI Community Toolkit. Thank you for your contributions! |
0 commit comments