Skip to content

Commit 6d37c38

Browse files
authored
Merge branch 'CommunityToolkit:main' into main
2 parents 6fc067d + c0a20b0 commit 6d37c38

8 files changed

+3808
-0
lines changed

.github/copilot-instructions.md

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# Overview
2+
This document provides guidelines for using GitHub Copilot to contribute to the .NET MAUI Community Toolkit. It includes instructions on setting up your environment, writing code, and following best practices specific to .NET MAUI.
3+
4+
## Prerequisites
5+
1. Install the latest stable (.NET SDK)[https://dotnet.microsoft.com/en-us/download].
6+
2. Install .NET MAUI workloads (we recommend using Visual Studio installer).
7+
8+
## Setting Up GitHub Copilot
9+
1. Ensure you have GitHub Copilot installed and enabled in Visual Studio.
10+
2. Familiarize yourself with the basic usage of GitHub Copilot by reviewing the (official documentation)[https://docs.github.com/en/copilot].
11+
12+
## Writing Code with GitHub Copilot
13+
### General Guidelines
14+
* Use GitHub Copilot to assist with code completion, documentation, and generating boilerplate code.
15+
* Always review and test the code suggested by GitHub Copilot to ensure it meets the project's standards and requirements.
16+
17+
### Specific to .NET MAUI
18+
* Ensure that any UI components or controls are compatible with .NET MAUI.
19+
* Avoid using Xamarin.Forms-specific code unless there is a direct .NET MAUI equivalent.
20+
* Follow the project's coding style and best practices as outlined in the (contributing)[https://github.com/CommunityToolkit/Maui/blob/main/CONTRIBUTING.md] document.
21+
22+
## Best Practices
23+
* Use **Trace.WriteLine()** for debug logging instead of **Debug.WriteLine()**.
24+
* Include a **CancellationToken** as a parameter for methods returning **Task** or **ValueTask**.
25+
* Use **is** for null checking and type checking.
26+
* Use file-scoped namespaces to reduce code verbosity.
27+
* Avoid using the **!** null forgiving operator.
28+
** Follow naming conventions for enums and property names.
29+
30+
### Debug Logging
31+
* Always use `Trace.WriteLine()` instead of `Debug.WriteLine` for debug logging because `Debug.WriteLine` is removed by the compiler in Release builds
32+
33+
### Methods Returning Task and ValueTask
34+
* Always include a `CancellationToken` as a parameter to every method returning `Task` or `ValueTask`
35+
* If the method is public, provide a the default value for the `CancellationToken` (e.g. `CancellationToken token = default`)
36+
* If the method is not public, do not provide a default value for the `CancellationToken`
37+
* 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.
38+
39+
### Enums
40+
* Always use `Unknown` at index 0 for return types that may have a value that is not known
41+
* Always use `Default` at index 0 for option types that can use the system default option
42+
* Follow naming guidelines for tense... `SensorSpeed` not `SensorSpeeds`
43+
* 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.
44+
45+
### Property Names
46+
* 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.
47+
48+
### Units
49+
* 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.
50+
51+
### Pattern matching
52+
#### Null checking
53+
* Prefer using `is` when checking for null instead of `==`.
54+
55+
e.g.
56+
57+
```csharp
58+
// null
59+
if (something is null)
60+
{
61+
62+
}
63+
64+
// or not null
65+
if (something is not null)
66+
{
67+
68+
}
69+
```
70+
71+
* 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.
72+
73+
#### Type checking
74+
* Prefer `is` when checking for types instead of casting.
75+
76+
e.g.
77+
78+
```csharp
79+
if (something is Bucket bucket)
80+
{
81+
bucket.Empty();
82+
}
83+
```
84+
85+
### File Scoped Namespaces
86+
* 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.
87+
88+
e.g.
89+
90+
```csharp
91+
namespace CommunityToolkit.Maui.Converters;
92+
93+
using System;
94+
95+
class BoolToObjectConverter
96+
{
97+
}
98+
```
99+
100+
### Braces
101+
Please use `{ }` after `if`, `for`, `foreach`, `do`, `while`, etc.
102+
103+
e.g.
104+
105+
```csharp
106+
if (something is not null)
107+
{
108+
ActOnIt();
109+
}
110+
```
111+
112+
### `NotImplementedException`
113+
* 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.'"
114+
In other words, `NotImplementedException` implies that a feature is still in development, indicating that the Pull Request is incomplete.
115+
116+
### Bug Fixes
117+
If you're looking for something to fix, please browse [open issues](https://github.com/CommunityToolkit/Maui/issues).
118+
119+
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:
120+
121+
* We do **not** use the `private` keyword as it is the default accessibility level in C#.
122+
* We will **not** use `_` or `s_` as a prefix for internal or private field names
123+
* We will use `camelCaseFieldName` for naming internal or private fields in both instance and static implementations
124+
125+
Read and follow our [Pull Request template](https://github.com/CommunityToolkit/Maui/blob/main/.github/PULL_REQUEST_TEMPLATE.md)
126+
127+
## Submitting Contributions
128+
1. Fork the repository and create a new branch for your changes.
129+
2. Implement your changes using GitHub Copilot as needed.
130+
3. Ensure your changes include tests, samples, and documentation.
131+
4. Open a pull request and follow the [Pull Request template](https://github.com/CommunityToolkit/Maui/blob/main/.github/PULL_REQUEST_TEMPLATE.md).
132+
133+
## Additional Resources
134+
- (GitHub Copilot Documentation)[https://docs.github.com/en/copilot]
135+
- (.NET MAUI Documentation)[https://learn.microsoft.com/en-us/dotnet/maui/]
136+
137+
By following these guidelines, you can effectively use GitHub Copilot to contribute to the .NET MAUI Community Toolkit. Thank you for your contributions!
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Async Programming Best Practices
2+
3+
This cheat sheet should serve as a quick reminder of best practices when writing asynchronous code. Following these guidelines will help you avoid common pitfalls such as unobserved exceptions, deadlocks, and unexpected UI blocking.
4+
5+
## DOs
6+
- **Always Await Your Tasks:**
7+
Always use the `await` keyword on async operations to ensure exceptions are captured and to avoid blocking the calling thread.
8+
- **Use Async Task/Task<T> Methods:**
9+
Prefer returning `Task` or `Task<T>` over `async void` so that exceptions can be observed, and methods are easily composable and testable.
10+
- **Name Methods with the "Async" Suffix:**
11+
Clearly differentiate asynchronous methods (e.g., `GetDataAsync()`) from synchronous ones, if there's a synchronous counterpart.
12+
- **Pass Cancellation Tokens:**
13+
Allow cancellation by accepting a `CancellationToken` in async methods.
14+
- **Use ConfigureAwait(false) When Appropriate:**
15+
In library code use `ConfigureAwait(false)` to avoid unnecessary context switches and potential deadlocks.
16+
- **Keep Async Code “Async All the Way”:**
17+
Propagate async all the way from the entry point (like event handlers or controller actions) rather than mixing sync and async code.
18+
- **Report Progress and Handle Exceptions Properly:**
19+
Use tools like `IProgress<T>` to report progress and always catch exceptions at the appropriate level when awaiting tasks.
20+
21+
## DON'Ts
22+
- **Avoid async void Methods:**
23+
Except for event handlers and overriding methods, never use `async void` because their exceptions are not observable and they're difficult to test.
24+
- **Don't Block on Async Code:**
25+
Avoid using `.Wait()` or `.Result` as these can lead to deadlocks and wrap exceptions in `AggregateException`. If you must block, consider using `GetAwaiter().GetResult()`.
26+
- **Don't Mix Blocking and Async Code:**
27+
Blocking the calling thread in an otherwise async flow (e.g., by mixing synchronous calls with async ones) may cause deadlocks and performance issues.
28+
- **Avoid Wrapping Return Task in Try/Catch or Using Blocks:**
29+
When a method returns a `Task`, wrapping it in a try/catch or using block may lead to unexpected behaviour because the task completes outside those blocks. For these scenarios use `async/await`.
30+
- **Don't Overuse Fire-and-Forget Patterns:**
31+
Unobserved tasks (fire-and-forget) can swallow exceptions and cause race conditions—if needed, use a “safe fire-and-forget” pattern with proper error handling.
32+

0 commit comments

Comments
 (0)