Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f3d36c9

Browse files
committedDec 18, 2024·
Initialize
1 parent 695ac5e commit f3d36c9

27 files changed

+1645
-0
lines changed
 

‎.editorconfig

+186
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
root = true
2+
3+
# All files
4+
[*]
5+
indent_style = space
6+
tab_width = 4
7+
indent_size = 4
8+
dotnet_style_readonly_field = true:suggestion
9+
dotnet_style_qualification_for_field = false:silent
10+
dotnet_style_qualification_for_property = false:silent
11+
dotnet_style_qualification_for_method = false:silent
12+
dotnet_style_qualification_for_event = false:silent
13+
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
14+
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
15+
dotnet_style_predefined_type_for_member_access = true:silent
16+
dotnet_code_quality_unused_parameters = all:suggestion
17+
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
18+
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
19+
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
20+
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
21+
dotnet_style_allow_statement_immediately_after_block_experimental = true:silent
22+
dotnet_style_allow_multiple_blank_lines_experimental = true:silent
23+
dotnet_style_null_propagation = true:suggestion
24+
dotnet_style_coalesce_expression = true:suggestion
25+
dotnet_style_prefer_auto_properties = true:silent
26+
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
27+
dotnet_style_object_initializer = true:suggestion
28+
dotnet_style_collection_initializer = true:suggestion
29+
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
30+
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
31+
dotnet_style_prefer_conditional_expression_over_return = true:silent
32+
dotnet_style_explicit_tuple_names = true:suggestion
33+
dotnet_style_prefer_inferred_tuple_names = true:suggestion
34+
dotnet_style_prefer_simplified_interpolation = true:suggestion
35+
dotnet_style_prefer_compound_assignment = true:suggestion
36+
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
37+
dotnet_style_namespace_match_folder = true:suggestion
38+
end_of_line = crlf
39+
dotnet_style_operator_placement_when_wrapping = beginning_of_line
40+
41+
# Xml files
42+
[*.xml]
43+
indent_size = 2
44+
45+
[*.cs]
46+
47+
# WFO1000: A property should determine its property content serialization with the DesignerSerializationVisibilityAttribute, DefaultValueAttribute or the ShouldSerializeProperty method
48+
dotnet_diagnostic.WFO1000.severity = silent
49+
50+
#### Adlandırma stilleri ####
51+
52+
# Adlandırma kuralları
53+
54+
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
55+
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
56+
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
57+
58+
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
59+
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
60+
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
61+
62+
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
63+
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
64+
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
65+
66+
# Sembol belirtimleri
67+
68+
dotnet_naming_symbols.interface.applicable_kinds = interface
69+
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
70+
dotnet_naming_symbols.interface.required_modifiers =
71+
72+
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
73+
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
74+
dotnet_naming_symbols.types.required_modifiers =
75+
76+
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
77+
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
78+
dotnet_naming_symbols.non_field_members.required_modifiers =
79+
80+
# Adlandırma stilleri
81+
82+
dotnet_naming_style.begins_with_i.required_prefix = I
83+
dotnet_naming_style.begins_with_i.required_suffix =
84+
dotnet_naming_style.begins_with_i.word_separator =
85+
dotnet_naming_style.begins_with_i.capitalization = pascal_case
86+
87+
dotnet_naming_style.pascal_case.required_prefix =
88+
dotnet_naming_style.pascal_case.required_suffix =
89+
dotnet_naming_style.pascal_case.word_separator =
90+
dotnet_naming_style.pascal_case.capitalization = pascal_case
91+
92+
dotnet_naming_style.pascal_case.required_prefix =
93+
dotnet_naming_style.pascal_case.required_suffix =
94+
dotnet_naming_style.pascal_case.word_separator =
95+
dotnet_naming_style.pascal_case.capitalization = pascal_case
96+
csharp_space_around_binary_operators = before_and_after
97+
csharp_indent_labels = one_less_than_current
98+
csharp_using_directive_placement = outside_namespace:silent
99+
csharp_style_prefer_switch_expression = true:suggestion
100+
csharp_style_prefer_pattern_matching = true:silent
101+
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
102+
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
103+
csharp_style_prefer_not_pattern = true:suggestion
104+
csharp_style_prefer_extended_property_pattern = true:suggestion
105+
csharp_prefer_static_local_function = true:suggestion
106+
csharp_prefer_simple_using_statement = true:suggestion
107+
csharp_prefer_braces = true:silent
108+
csharp_style_namespace_declarations = block_scoped:silent
109+
csharp_style_prefer_method_group_conversion = true:silent
110+
csharp_style_prefer_top_level_statements = true:silent
111+
csharp_style_conditional_delegate_call = true:suggestion
112+
csharp_style_var_when_type_is_apparent = false:silent
113+
csharp_style_var_for_built_in_types = false:silent
114+
csharp_style_var_elsewhere = false:silent
115+
csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent
116+
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent
117+
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent
118+
csharp_style_prefer_tuple_swap = true:suggestion
119+
csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
120+
csharp_style_prefer_range_operator = true:suggestion
121+
csharp_style_prefer_index_operator = true:suggestion
122+
csharp_style_prefer_local_over_anonymous_function = true:suggestion
123+
csharp_prefer_simple_default_expression = true:suggestion
124+
csharp_style_prefer_null_check_over_type_check = true:suggestion
125+
csharp_style_throw_expression = true:suggestion
126+
csharp_style_prefer_utf8_string_literals = true:suggestion
127+
csharp_style_expression_bodied_lambdas = true:silent
128+
csharp_style_expression_bodied_accessors = true:silent
129+
csharp_style_expression_bodied_indexers = true:silent
130+
csharp_style_expression_bodied_properties = true:silent
131+
csharp_style_expression_bodied_operators = false:silent
132+
csharp_style_expression_bodied_constructors = false:silent
133+
csharp_style_expression_bodied_methods = false:silent
134+
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
135+
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
136+
csharp_style_deconstructed_variable_declaration = true:suggestion
137+
csharp_style_inlined_variable_declaration = true:suggestion
138+
csharp_style_expression_bodied_local_functions = false:silent
139+
140+
[*.vb]
141+
#### Adlandırma stilleri ####
142+
143+
# Adlandırma kuralları
144+
145+
dotnet_naming_rule.interface_should_be_i_ile_başlar.severity = suggestion
146+
dotnet_naming_rule.interface_should_be_i_ile_başlar.symbols = interface
147+
dotnet_naming_rule.interface_should_be_i_ile_başlar.style = i_ile_başlar
148+
149+
dotnet_naming_rule.türler_should_be_baş_harfleri_büyük_olmak_üzere_bitişik.severity = suggestion
150+
dotnet_naming_rule.türler_should_be_baş_harfleri_büyük_olmak_üzere_bitişik.symbols = türler
151+
dotnet_naming_rule.türler_should_be_baş_harfleri_büyük_olmak_üzere_bitişik.style = baş_harfleri_büyük_olmak_üzere_bitişik
152+
153+
dotnet_naming_rule.alan_olmayan_üyeler_should_be_baş_harfleri_büyük_olmak_üzere_bitişik.severity = suggestion
154+
dotnet_naming_rule.alan_olmayan_üyeler_should_be_baş_harfleri_büyük_olmak_üzere_bitişik.symbols = alan_olmayan_üyeler
155+
dotnet_naming_rule.alan_olmayan_üyeler_should_be_baş_harfleri_büyük_olmak_üzere_bitişik.style = baş_harfleri_büyük_olmak_üzere_bitişik
156+
157+
# Sembol belirtimleri
158+
159+
dotnet_naming_symbols.interface.applicable_kinds = interface
160+
dotnet_naming_symbols.interface.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
161+
dotnet_naming_symbols.interface.required_modifiers =
162+
163+
dotnet_naming_symbols.türler.applicable_kinds = class, struct, interface, enum
164+
dotnet_naming_symbols.türler.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
165+
dotnet_naming_symbols.türler.required_modifiers =
166+
167+
dotnet_naming_symbols.alan_olmayan_üyeler.applicable_kinds = property, event, method
168+
dotnet_naming_symbols.alan_olmayan_üyeler.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
169+
dotnet_naming_symbols.alan_olmayan_üyeler.required_modifiers =
170+
171+
# Adlandırma stilleri
172+
173+
dotnet_naming_style.i_ile_başlar.required_prefix = I
174+
dotnet_naming_style.i_ile_başlar.required_suffix =
175+
dotnet_naming_style.i_ile_başlar.word_separator =
176+
dotnet_naming_style.i_ile_başlar.capitalization = pascal_case
177+
178+
dotnet_naming_style.baş_harfleri_büyük_olmak_üzere_bitişik.required_prefix =
179+
dotnet_naming_style.baş_harfleri_büyük_olmak_üzere_bitişik.required_suffix =
180+
dotnet_naming_style.baş_harfleri_büyük_olmak_üzere_bitişik.word_separator =
181+
dotnet_naming_style.baş_harfleri_büyük_olmak_üzere_bitişik.capitalization = pascal_case
182+
183+
dotnet_naming_style.baş_harfleri_büyük_olmak_üzere_bitişik.required_prefix =
184+
dotnet_naming_style.baş_harfleri_büyük_olmak_üzere_bitişik.required_suffix =
185+
dotnet_naming_style.baş_harfleri_büyük_olmak_üzere_bitişik.word_separator =
186+
dotnet_naming_style.baş_harfleri_büyük_olmak_üzere_bitişik.capitalization = pascal_case

‎.github/FUNDING.yml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# These are supported funding model platforms
2+
3+
github: # [Taiizor]
4+
patreon: # Replace with a single Patreon username
5+
open_collective: # Replace with a single Open Collective username
6+
ko_fi: # Replace with a single Ko-fi username
7+
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8+
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9+
liberapay: # Replace with a single Liberapay username
10+
issuehunt: # Replace with a single IssueHunt username
11+
otechie: # Replace with a single Otechie username
12+
custom: ['https://www.nuget.org/profiles/Taiizor', 'www.vegalya.com', 'www.soferity.com']
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Bug report
2+
description: File a bug report
3+
labels: ["bug"]
4+
body:
5+
- type: markdown
6+
attributes:
7+
value: |
8+
Thanks for taking the time to fill out this bug report!
9+
Seriously consider creating and linking to a test repo which takes absolutely minimal setup to illustrate how reproduce the problem.
10+
- type: textarea
11+
id: bug-explanation
12+
attributes:
13+
label: Bug explanation
14+
description: |
15+
- Tell us what is the problem and what did you expect to happen.
16+
- Explain the different steps to reproduce the bug.
17+
- Provide a minimal and reproducible example either with code snippets or ideally an example repository.
18+
19+
You can attach some screenshots or/and videos to better illustrate the problem.
20+
placeholder: Explain the problem...
21+
validations:
22+
required: true
23+
- type: input
24+
id: version
25+
attributes:
26+
label: Version
27+
description: What version of our package are you running?
28+
placeholder: "Example: 1.2.3.4"
29+
validations:
30+
required: true

‎.github/ISSUE_TEMPLATE/config.yml

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
blank_issues_enabled: false
2+
contact_links:
3+
- name: GitHub discussion tab
4+
url: https://github.com/Taiizor/UUID/discussions
5+
about: Please ask and answer questions here
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
name: Feature request
3+
about: Suggest an idea for this project
4+
title: ''
5+
labels: enhancement
6+
assignees: ''
7+
8+
---
9+
10+
**Is your feature request related to a problem? Please describe.**
11+
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12+
13+
**Describe the solution you'd like**
14+
A clear and concise description of what you want to happen.
15+
16+
**Describe alternatives you've considered**
17+
A clear and concise description of any alternative solutions or features you've considered.
18+
19+
**Additional context**
20+
Add any other context or screenshots about the feature request here.

‎.github/dependabot.yml

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: nuget
4+
directory: "/"
5+
schedule:
6+
interval: daily
7+
time: "03:00"
8+
open-pull-requests-limit: 10

‎.github/workflows/congratulations.yml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: Congratulations
2+
3+
on: [pull_request_target, issues]
4+
5+
jobs:
6+
Congratulation:
7+
8+
runs-on: ubuntu-latest
9+
10+
permissions:
11+
issues: write
12+
pull-requests: write
13+
14+
steps:
15+
- uses: actions/first-interaction@v1
16+
with:
17+
repo-token: ${{ secrets.GITHUB_TOKEN }}
18+
issue-message: "We're grateful you made your first issue notification. You can be sure that a response will be made as soon as possible."
19+
pr-message: "We're grateful you made your first pull request notification. You can be sure that a response will be made as soon as possible."

‎.images/Logo.png

3.1 KB
Loading

‎.images/Template.png

31 KB
Loading

‎CODE_OF_CONDUCT.md

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Contributor Covenant Code of Conduct
2+
3+
## Our Pledge
4+
5+
We as members, contributors, and leaders pledge to make participation in our
6+
community a harassment-free experience for everyone, regardless of age, body
7+
size, visible or invisible disability, ethnicity, sex characteristics, gender
8+
identity and expression, level of experience, education, socio-economic status,
9+
nationality, personal appearance, race, caste, color, religion, or sexual
10+
identity and orientation.
11+
12+
We pledge to act and interact in ways that contribute to an open, welcoming,
13+
diverse, inclusive, and healthy community.
14+
15+
## Our Standards
16+
17+
Examples of behavior that contributes to a positive environment for our
18+
community include:
19+
20+
* Demonstrating empathy and kindness toward other people
21+
* Being respectful of differing opinions, viewpoints, and experiences
22+
* Giving and gracefully accepting constructive feedback
23+
* Accepting responsibility and apologizing to those affected by our mistakes,
24+
and learning from the experience
25+
* Focusing on what is best not just for us as individuals, but for the overall
26+
community
27+
28+
Examples of unacceptable behavior include:
29+
30+
* The use of sexualized language or imagery, and sexual attention or advances of
31+
any kind
32+
* Trolling, insulting or derogatory comments, and personal or political attacks
33+
* Public or private harassment
34+
* Publishing others' private information, such as a physical or email address,
35+
without their explicit permission
36+
* Other conduct which could reasonably be considered inappropriate in a
37+
professional setting
38+
39+
## Enforcement Responsibilities
40+
41+
Community leaders are responsible for clarifying and enforcing our standards of
42+
acceptable behavior and will take appropriate and fair corrective action in
43+
response to any behavior that they deem inappropriate, threatening, offensive,
44+
or harmful.
45+
46+
Community leaders have the right and responsibility to remove, edit, or reject
47+
comments, commits, code, wiki edits, issues, and other contributions that are
48+
not aligned to this Code of Conduct, and will communicate reasons for moderation
49+
decisions when appropriate.
50+
51+
## Scope
52+
53+
This Code of Conduct applies within all community spaces, and also applies when
54+
an individual is officially representing the community in public spaces.
55+
Examples of representing our community include using an official email address,
56+
posting via an official social media account, or acting as an appointed
57+
representative at an online or offline event.
58+
59+
## Enforcement
60+
61+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
62+
reported to the community leaders responsible for enforcement at
63+
[INSERT CONTACT METHOD].
64+
All complaints will be reviewed and investigated promptly and fairly.
65+
66+
All community leaders are obligated to respect the privacy and security of the
67+
reporter of any incident.
68+
69+
## Enforcement Guidelines
70+
71+
Community leaders will follow these Community Impact Guidelines in determining
72+
the consequences for any action they deem in violation of this Code of Conduct:
73+
74+
### 1. Correction
75+
76+
**Community Impact**: Use of inappropriate language or other behavior deemed
77+
unprofessional or unwelcome in the community.
78+
79+
**Consequence**: A private, written warning from community leaders, providing
80+
clarity around the nature of the violation and an explanation of why the
81+
behavior was inappropriate. A public apology may be requested.
82+
83+
### 2. Warning
84+
85+
**Community Impact**: A violation through a single incident or series of
86+
actions.
87+
88+
**Consequence**: A warning with consequences for continued behavior. No
89+
interaction with the people involved, including unsolicited interaction with
90+
those enforcing the Code of Conduct, for a specified period of time. This
91+
includes avoiding interactions in community spaces as well as external channels
92+
like social media. Violating these terms may lead to a temporary or permanent
93+
ban.
94+
95+
### 3. Temporary Ban
96+
97+
**Community Impact**: A serious violation of community standards, including
98+
sustained inappropriate behavior.
99+
100+
**Consequence**: A temporary ban from any sort of interaction or public
101+
communication with the community for a specified period of time. No public or
102+
private interaction with the people involved, including unsolicited interaction
103+
with those enforcing the Code of Conduct, is allowed during this period.
104+
Violating these terms may lead to a permanent ban.
105+
106+
### 4. Permanent Ban
107+
108+
**Community Impact**: Demonstrating a pattern of violation of community
109+
standards, including sustained inappropriate behavior, harassment of an
110+
individual, or aggression toward or disparagement of classes of individuals.
111+
112+
**Consequence**: A permanent ban from any sort of public interaction within the
113+
community.
114+
115+
## Attribution
116+
117+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118+
version 2.1, available at
119+
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
120+
121+
Community Impact Guidelines were inspired by
122+
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
123+
124+
For answers to common questions about this code of conduct, see the FAQ at
125+
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
126+
[https://www.contributor-covenant.org/translations][translations].
127+
128+
[homepage]: https://www.contributor-covenant.org
129+
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
130+
[Mozilla CoC]: https://github.com/mozilla/diversity
131+
[FAQ]: https://www.contributor-covenant.org/faq
132+
[translations]: https://www.contributor-covenant.org/translations

‎LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Taiizor
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

‎NuGet.Config

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
3+
<configuration>
4+
<packageSources>
5+
<clear />
6+
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
7+
<add key="dotnet6" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6/nuget/v3/index.json" />
8+
<add key="dotnet7" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json" />
9+
<add key="dotnet8" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet8/nuget/v3/index.json" />
10+
<add key="dotnet9" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet9/nuget/v3/index.json" />
11+
<add key="dotnet10" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet10/nuget/v3/index.json" />
12+
<add key="public" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public/nuget/v3/index.json" />
13+
<add key="xamarin" value="https://pkgs.dev.azure.com/azure-public/vside/_packaging/xamarin-impl/nuget/v3/index.json" />
14+
</packageSources>
15+
</configuration>

‎README.md

+212
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
![Logo](.images/Logo.png)
2+
3+
![Dot-Net-Framework-Version](https://img.shields.io/badge/.NET%20Framework-%3E%3D4.8-blue)
4+
![Dot-Net-Standard-Version](https://img.shields.io/badge/.NET%20Standard-%3E%3D2.0-blue)
5+
![Dot-Net-Version](https://img.shields.io/badge/.NET-%3E%3D6.0-blue)
6+
![C-Sharp-Version](https://img.shields.io/badge/C%23-Preview-blue.svg)
7+
[![IDE-Version](https://img.shields.io/badge/IDE-VS2022-blue.svg)](https://visualstudio.microsoft.com/downloads)
8+
[![NuGet-Version](https://img.shields.io/nuget/v/UUID.svg?label=NuGet)](https://www.nuget.org/packages/UUID)
9+
[![NuGet-Download](https://img.shields.io/nuget/dt/UUID?label=Download)](https://www.nuget.org/api/v2/package/UUID)
10+
[![Stack Overflow](https://img.shields.io/badge/Stack%20Overflow-UUID-orange.svg)](https://stackoverflow.com/questions/tagged/uuid)
11+
12+
[![.NET](https://github.com/Taiizor/UUID/actions/workflows/dotnet.yml/badge.svg)](https://github.com/Taiizor/UUID/actions/workflows/dotnet.yml)
13+
[![CodeQL](https://github.com/Taiizor/UUID/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/Taiizor/UUID/actions/workflows/codeql-analysis.yml)
14+
[![.NET Desktop](https://github.com/Taiizor/UUID/actions/workflows/dotnet-desktop.yml/badge.svg)](https://github.com/Taiizor/UUID/actions/workflows/dotnet-desktop.yml)
15+
16+
[![Discord-Server](https://img.shields.io/discord/932386235538878534?label=Discord)](https://discord.gg/nxG977byXb)
17+
18+
# Welcome to UUID
19+
UUID is a modern and efficient unique identifier generator for .NET ecosystem. This high-performance library is designed for modern distributed systems, providing thread-safe operations and time-ordered identifiers with enhanced security features.
20+
21+
## Contributors
22+
23+
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
24+
25+
<table>
26+
<tr>
27+
<td align="center">
28+
<a href="https://github.com/Taiizor">
29+
<img src="https://avatars3.githubusercontent.com/u/41683699?s=460&v=4" width="80px;" alt="Taiizor"/>
30+
<br/>
31+
<sub>
32+
<b>Taiizor</b>
33+
</sub>
34+
</a>
35+
<br/>
36+
<a href="https://github.com/Taiizor/UUID/commits?author=Taiizor" title="Code">💻</a>
37+
<a href="https://www.vegalya.com" title="Ideas & Planning, Feedback">🤔</a>
38+
</td>
39+
</tr>
40+
</table>
41+
42+
This project follows the [all contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
43+
44+
## Backers
45+
46+
<table>
47+
<tr>
48+
<td align="center">
49+
<a href="https://github.com/Vegalya">
50+
<img src="https://avatars3.githubusercontent.com/u/98421771?s=200&v=4" width="80px;" alt="Vegalya"/>
51+
<br/>
52+
<sub>
53+
<b>Vegalya</b>
54+
</sub>
55+
</a>
56+
<br/>
57+
<a href="https://github.com/Vegalya" target="_blank" title="Content">🖋</a>
58+
</td>
59+
<td align="center">
60+
<a href="https://github.com/Soferity">
61+
<img src="https://avatars3.githubusercontent.com/u/63516515?s=200&v=4" width="80px;" alt="Soferity"/>
62+
<br/>
63+
<sub>
64+
<b>Soferity</b>
65+
</sub>
66+
</a>
67+
<br/>
68+
<a href="https://github.com/Soferity" target="_blank" title="Content">🖋</a>
69+
</td>
70+
</tr>
71+
</table>
72+
73+
## Platform support
74+
75+
UUID works on .NET Framework, .NET Standard, .NET Core and .NET.
76+
77+
<table>
78+
<thead>
79+
<tr>
80+
<th>.NET implementation</th>
81+
<th>Version support</th>
82+
</tr>
83+
</thead>
84+
<tbody>
85+
<tr>
86+
<td>.NET and .NET Core</td>
87+
<td>2.0, 2.1, 2.2, 3.0, 3.1, 5.0, 6.0, 7.0, 8.0, 9.0</td>
88+
</tr>
89+
<tr>
90+
<td>.NET Framework</td>
91+
<td>4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1</td>
92+
</tr>
93+
<tr>
94+
<td>Mono</td>
95+
<td>5.4, 6.4</td>
96+
</tr>
97+
<tr>
98+
<td>Xamarin.iOS</td>
99+
<td>10.14, 12.16</td>
100+
</tr>
101+
<tr>
102+
<td>Xamarin.Mac</td>
103+
<td>3.8, 5.16</td>
104+
</tr>
105+
<tr>
106+
<td>Xamarin.Android</td>
107+
<td>8.0, 10.0</td>
108+
</tr>
109+
<tr>
110+
<td>Universal Windows Platform</td>
111+
<td>10.0.16299, TBD</td>
112+
</tr>
113+
<tr>
114+
<td>Unity</td>
115+
<td>2018.1</td>
116+
</tr>
117+
</tbody>
118+
</table>
119+
120+
Binaries for all platforms are built from a single Visual Studio Project. You will need the latset [Visual Studio](https://visualstudio.microsoft.com/downloads) to build or contribute to UUID.
121+
122+
## Features
123+
124+
- **High Performance & Thread Safety**
125+
- Thread-safe operations optimized for performance
126+
- Thread-local secure random generation
127+
- Efficient memory usage with 16-byte format
128+
129+
- **Time-Based Ordering**
130+
- Natural sorting based on creation time
131+
- Monotonic timestamps for consistent ordering
132+
- Perfect for distributed systems and databases
133+
134+
- **Security**
135+
- Cryptographically secure random generation
136+
- Enhanced protection against prediction and collision
137+
138+
- **Multiple Format Support**
139+
- Base32 encoding for URL-friendly strings
140+
- Base64 encoding for compact representation
141+
- System.Guid compatibility
142+
- Efficient string parsing and formatting
143+
144+
- **Rich API**
145+
- Implicit/explicit conversion operators
146+
- Comparison and equality operations
147+
- Comprehensive test coverage
148+
- Cross-platform compatibility
149+
150+
## Getting started
151+
152+
UUID is distributed via Microsofts package manager [NuGet](https://www.nuget.org). We refer to [this page](https://docs.microsoft.com/en-gb/nuget) for detailed descriptions on how to get started/use NuGet. Here is a link to the [UUID NuGet package](https://www.nuget.org/packages/UUID).
153+
You can grab a copy of the library on NuGet by running:
154+
155+
By Package Manager (PM):
156+
```sh
157+
Install-Package UUID
158+
```
159+
160+
By .NET CLI:
161+
```sh
162+
dotnet add package UUID
163+
```
164+
165+
## Quick Start
166+
167+
```csharp
168+
using UUID;
169+
170+
// Generate a new UUID
171+
UUID id = UUID.New();
172+
173+
// Convert to string formats
174+
string str = id.ToString(); // Standard format
175+
string base32 = id.ToBase32(); // URL-friendly
176+
string base64 = id.ToBase64(); // Compact
177+
178+
// Parse from string
179+
UUID parsed = UUID.Parse(str);
180+
bool success = UUID.TryParse(str, out UUID result);
181+
182+
// System.Guid compatibility
183+
Guid guid = id.ToGuid();
184+
UUID fromGuid = UUID.FromGuid(guid);
185+
186+
// Implicit/Explicit conversions
187+
UUID implicitFromGuid = guid; // Implicit
188+
Guid explicitToGuid = (Guid)id; // Explicit
189+
190+
// Time component
191+
DateTimeOffset timestamp = id.Time;
192+
193+
// Comparison operations
194+
bool equals = id == parsed;
195+
bool lessThan = id < parsed;
196+
```
197+
198+
## Documentation and Support
199+
200+
To learn more about UUID, check out our [documentation](https://github.com/Taiizor/UUID/wiki). You can get help via:
201+
202+
* [Stack Overflow](https://stackoverflow.com/questions/tagged/uuid)
203+
* [Discord](https://discord.gg/nxG977byXb)
204+
* [Issue Tracker](https://github.com/Taiizor/UUID/issues)
205+
206+
## Contributing
207+
208+
Would you like to help make UUID even better? We keep a list of issues that are approachable for newcomers under the [solved](https://github.com/Taiizor/UUID/issues?q=is%3Aissue+label%3Asolved) label (accessible only when logged into GitHub). Before starting work on a pull request, we suggest commenting on, or raising, an issue on the issue tracker so that we can help and coordinate efforts.
209+
210+
When contributing please keep in mind our [Code of Conduct](CODE_OF_CONDUCT.md).
211+
212+
_UUID is copyright &copy; 2024-2025 UUID Contributors - Provided under the [MIT License](LICENSE)._

‎UUID.sln

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
Microsoft Visual Studio Solution File, Format Version 12.00
2+
# Visual Studio Version 17
3+
VisualStudioVersion = 17.7.33808.371
4+
MinimumVisualStudioVersion = 10.0.40219.1
5+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3943FC00-5155-481C-ABD2-2F1E094589A0}"
6+
ProjectSection(SolutionItems) = preProject
7+
.editorconfig = .editorconfig
8+
global.json = global.json
9+
NuGet.Config = NuGet.Config
10+
EndProjectSection
11+
EndProject
12+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "demo", "demo", "{04361DC9-3E9F-481A-9489-068DE8688332}"
13+
EndProject
14+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{02D54F9E-8518-40C9-B2CD-2A4F8CA339A3}"
15+
EndProject
16+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A98F348B-49A9-43CB-924A-9F0A40CA88B2}"
17+
EndProject
18+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UUID.Demo", "demo\UUID.Demo\UUID.Demo.csproj", "{BDBE3439-450F-8792-3B14-6E8333921809}"
19+
EndProject
20+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UUID", "src\UUID\UUID.csproj", "{5CC30F3B-431B-496B-91F9-9FD12F079DBA}"
21+
EndProject
22+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UUID.Tests", "test\UUID.Tests\UUID.Tests.csproj", "{FC997986-74D3-F9FE-BA5C-376D348DF859}"
23+
EndProject
24+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmark", "benchmark", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
25+
EndProject
26+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UUID.Benchmarks", "benchmark\UUID.Benchmarks\UUID.Benchmarks.csproj", "{709ECC72-B71F-C590-0855-BB31582B4CFC}"
27+
EndProject
28+
Global
29+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
30+
Debug|Any CPU = Debug|Any CPU
31+
Release|Any CPU = Release|Any CPU
32+
EndGlobalSection
33+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
34+
{BDBE3439-450F-8792-3B14-6E8333921809}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35+
{BDBE3439-450F-8792-3B14-6E8333921809}.Debug|Any CPU.Build.0 = Debug|Any CPU
36+
{BDBE3439-450F-8792-3B14-6E8333921809}.Release|Any CPU.ActiveCfg = Release|Any CPU
37+
{BDBE3439-450F-8792-3B14-6E8333921809}.Release|Any CPU.Build.0 = Release|Any CPU
38+
{5CC30F3B-431B-496B-91F9-9FD12F079DBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39+
{5CC30F3B-431B-496B-91F9-9FD12F079DBA}.Debug|Any CPU.Build.0 = Debug|Any CPU
40+
{5CC30F3B-431B-496B-91F9-9FD12F079DBA}.Release|Any CPU.ActiveCfg = Release|Any CPU
41+
{5CC30F3B-431B-496B-91F9-9FD12F079DBA}.Release|Any CPU.Build.0 = Release|Any CPU
42+
{FC997986-74D3-F9FE-BA5C-376D348DF859}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43+
{FC997986-74D3-F9FE-BA5C-376D348DF859}.Debug|Any CPU.Build.0 = Debug|Any CPU
44+
{FC997986-74D3-F9FE-BA5C-376D348DF859}.Release|Any CPU.ActiveCfg = Release|Any CPU
45+
{FC997986-74D3-F9FE-BA5C-376D348DF859}.Release|Any CPU.Build.0 = Release|Any CPU
46+
{709ECC72-B71F-C590-0855-BB31582B4CFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
47+
{709ECC72-B71F-C590-0855-BB31582B4CFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
48+
{709ECC72-B71F-C590-0855-BB31582B4CFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
49+
{709ECC72-B71F-C590-0855-BB31582B4CFC}.Release|Any CPU.Build.0 = Release|Any CPU
50+
EndGlobalSection
51+
GlobalSection(SolutionProperties) = preSolution
52+
HideSolutionNode = FALSE
53+
EndGlobalSection
54+
GlobalSection(NestedProjects) = preSolution
55+
{BDBE3439-450F-8792-3B14-6E8333921809} = {04361DC9-3E9F-481A-9489-068DE8688332}
56+
{5CC30F3B-431B-496B-91F9-9FD12F079DBA} = {A98F348B-49A9-43CB-924A-9F0A40CA88B2}
57+
{FC997986-74D3-F9FE-BA5C-376D348DF859} = {02D54F9E-8518-40C9-B2CD-2A4F8CA339A3}
58+
{709ECC72-B71F-C590-0855-BB31582B4CFC} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
59+
EndGlobalSection
60+
GlobalSection(ExtensibilityGlobals) = postSolution
61+
SolutionGuid = {5DA4A105-4BC7-4943-9328-F7274E75FCB3}
62+
EndGlobalSection
63+
EndGlobal

‎benchmark/UUID.Benchmarks/Program.cs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using BenchmarkDotNet.Running;
2+
3+
namespace UUID.Benchmarks
4+
{
5+
internal class Program
6+
{
7+
static void Main(string[] args)
8+
{
9+
BenchmarkRunner.Run<UUIDBenchmarks>();
10+
}
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net9.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
<PlatformTarget>AnyCPU</PlatformTarget>
9+
<DebugType>pdbonly</DebugType>
10+
<DebugSymbols>true</DebugSymbols>
11+
<LangVersion>preview</LangVersion>
12+
<AnalysisLevel>preview</AnalysisLevel>
13+
</PropertyGroup>
14+
15+
<ItemGroup>
16+
<PackageReference Include="BenchmarkDotNet" Version="0.14.0" />
17+
</ItemGroup>
18+
19+
<ItemGroup>
20+
<ProjectReference Include="..\..\src\UUID\UUID.csproj" />
21+
</ItemGroup>
22+
23+
</Project>
+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
using BenchmarkDotNet.Attributes;
2+
using BenchmarkDotNet.Jobs;
3+
4+
namespace UUID.Benchmarks
5+
{
6+
[SimpleJob(RuntimeMoniker.Net90, launchCount: 1, warmupCount: 3, iterationCount: 5)]
7+
[MemoryDiagnoser]
8+
public class UUIDBenchmarks
9+
{
10+
private readonly byte[] _buffer = new byte[16];
11+
private readonly Guid _guid = Guid.NewGuid();
12+
private readonly UUID _uuid2 = UUID.New();
13+
private readonly UUID _uuid = UUID.New();
14+
private readonly string _uuidString;
15+
16+
public UUIDBenchmarks()
17+
{
18+
_uuidString = _uuid.ToString();
19+
}
20+
21+
[Benchmark(Baseline = true)]
22+
public UUID Generate_New()
23+
{
24+
return UUID.New();
25+
}
26+
27+
[Benchmark]
28+
public string Convert_ToString()
29+
{
30+
return _uuid.ToString();
31+
}
32+
33+
[Benchmark]
34+
public UUID Parse_FromString()
35+
{
36+
return UUID.Parse(_uuidString);
37+
}
38+
39+
[Benchmark]
40+
public bool TryParse_FromString()
41+
{
42+
return UUID.TryParse(_uuidString, out _);
43+
}
44+
45+
[Benchmark]
46+
public string Convert_ToBase32()
47+
{
48+
return _uuid.ToBase32();
49+
}
50+
51+
[Benchmark]
52+
public string Convert_ToBase64()
53+
{
54+
return _uuid.ToBase64();
55+
}
56+
57+
[Benchmark]
58+
public byte[] Convert_ToByteArray()
59+
{
60+
return _uuid.ToByteArray();
61+
}
62+
63+
[Benchmark]
64+
public bool Convert_TryWriteBytes()
65+
{
66+
return _uuid.TryWriteBytes(_buffer);
67+
}
68+
69+
[Benchmark]
70+
public bool Convert_TryWriteStringify()
71+
{
72+
char[] buffer = new char[32];
73+
return _uuid.TryWriteStringify(buffer);
74+
}
75+
76+
[Benchmark]
77+
public Guid Convert_ToGuid()
78+
{
79+
return _uuid.ToGuid();
80+
}
81+
82+
[Benchmark]
83+
public UUID Convert_FromGuid()
84+
{
85+
return UUID.FromGuid(_guid);
86+
}
87+
88+
[Benchmark]
89+
public bool Compare_Equals()
90+
{
91+
return _uuid.Equals(_uuid2);
92+
}
93+
94+
[Benchmark]
95+
public int Compare_CompareTo()
96+
{
97+
return _uuid.CompareTo(_uuid2);
98+
}
99+
100+
[Benchmark]
101+
public bool Compare_LessThan()
102+
{
103+
return _uuid < _uuid2;
104+
}
105+
106+
[Benchmark]
107+
public bool Compare_GreaterThan()
108+
{
109+
return _uuid > _uuid2;
110+
}
111+
}
112+
}

‎demo/UUID.Demo/Program.cs

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
namespace UUID.Demo
2+
{
3+
class Program
4+
{
5+
static async Task Main(string[] args)
6+
{
7+
Console.WriteLine("UUID Library Demo\n");
8+
9+
// 1. Basic UUID Operations
10+
Console.WriteLine("1. Basic UUID Operations:");
11+
UUID id = UUID.New();
12+
Console.WriteLine($"New UUID: {id}");
13+
14+
string str = id.ToString();
15+
Console.WriteLine($"String format: {str}");
16+
17+
UUID parsed = UUID.Parse(str);
18+
Console.WriteLine($"Parsed UUID: {parsed}");
19+
Console.WriteLine($"Equals original? {id == parsed}");
20+
21+
Console.WriteLine("\n2. Time and Random Components:");
22+
Console.WriteLine($"Timestamp: {id.Time}");
23+
Console.WriteLine($"Random component: {id.Random:x16}");
24+
25+
Console.WriteLine("\n3. Different Format Conversions:");
26+
Console.WriteLine($"Base32 format: {id.ToBase32()}");
27+
Console.WriteLine($"Base64 format: {id.ToBase64()}");
28+
29+
byte[] bytes = id.ToByteArray();
30+
Console.WriteLine($"Byte array length: {bytes.Length} bytes");
31+
32+
char[] buffer = new char[32];
33+
id.TryWriteStringify(buffer);
34+
Console.WriteLine($"String buffer content: {new string(buffer)}");
35+
36+
Console.WriteLine("\n4. Guid Conversions and Operators:");
37+
Guid guid = id.ToGuid();
38+
Console.WriteLine($"UUID -> Guid: {guid}");
39+
40+
UUID fromGuid = UUID.FromGuid(guid);
41+
Console.WriteLine($"Guid -> UUID: {fromGuid}");
42+
Console.WriteLine($"Equals original? {id == fromGuid}");
43+
44+
// Implicit/Explicit operators
45+
UUID implicitFromGuid = guid; // Implicit conversion
46+
Guid explicitToGuid = (Guid)id; // Explicit conversion
47+
Console.WriteLine($"Implicit/Explicit conversion successful? {implicitFromGuid == id && explicitToGuid == guid}");
48+
49+
Console.WriteLine("\n5. Binary Operations:");
50+
// TryWriteBytes example
51+
byte[] byteBuffer = new byte[16];
52+
bool writeSuccess = id.TryWriteBytes(byteBuffer);
53+
Console.WriteLine($"Write to byte buffer successful? {writeSuccess}");
54+
Console.WriteLine($"Byte buffer content: {BitConverter.ToString(byteBuffer).Replace("-", "")}");
55+
56+
// Direct byte array
57+
byte[] byteArray = id.ToByteArray();
58+
Console.WriteLine($"Direct byte array: {BitConverter.ToString(byteArray).Replace("-", "")}");
59+
60+
Console.WriteLine("\n6. Comparison Operations:");
61+
UUID id1 = new(); // Using parameterless constructor
62+
await Task.Delay(1); // Wait to ensure different timestamp
63+
UUID id2 = UUID.New();
64+
65+
Console.WriteLine($"UUID 1: {id1}");
66+
Console.WriteLine($"UUID 2: {id2}");
67+
Console.WriteLine($"UUID1 < UUID2: {id1 < id2}");
68+
Console.WriteLine($"UUID1 <= UUID2: {id1 <= id2}");
69+
Console.WriteLine($"UUID1 > UUID2: {id1 > id2}");
70+
Console.WriteLine($"UUID1 >= UUID2: {id1 >= id2}");
71+
72+
Console.WriteLine("\n7. Sorting and Thread Safety:");
73+
List<UUID> ids = new();
74+
for (int i = 0; i < 5; i++)
75+
{
76+
await Task.Delay(1); // Wait for different timestamps
77+
ids.Add(UUID.New());
78+
}
79+
80+
Console.WriteLine("Unsorted UUIDs:");
81+
foreach (UUID uuid in ids)
82+
{
83+
Console.WriteLine($" {uuid} - Time: {uuid.Time:yyyy-MM-dd HH:mm:ss.fff}");
84+
}
85+
86+
ids.Sort();
87+
Console.WriteLine("\nSorted UUIDs:");
88+
foreach (UUID uuid in ids)
89+
{
90+
Console.WriteLine($" {uuid} - Time: {uuid.Time:yyyy-MM-dd HH:mm:ss.fff}");
91+
}
92+
93+
Console.WriteLine("\n8. Thread-Safe UUID Generation:");
94+
HashSet<UUID> set = new();
95+
List<Task> tasks = new();
96+
97+
for (int i = 0; i < 5; i++)
98+
{
99+
tasks.Add(Task.Run(() =>
100+
{
101+
for (int j = 0; j < 1000; j++)
102+
{
103+
UUID uuid = UUID.New();
104+
lock (set)
105+
{
106+
if (!set.Add(uuid))
107+
{
108+
Console.WriteLine("Warning: UUID collision detected!");
109+
}
110+
}
111+
}
112+
}));
113+
}
114+
115+
await Task.WhenAll(tasks);
116+
Console.WriteLine($"Generated {set.Count} unique UUIDs across multiple threads");
117+
}
118+
}
119+
}

‎demo/UUID.Demo/UUID.Demo.csproj

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net9.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
<LangVersion>preview</LangVersion>
9+
<AnalysisLevel>preview</AnalysisLevel>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<ProjectReference Include="..\..\src\UUID\UUID.csproj" />
14+
</ItemGroup>
15+
16+
</Project>

‎global.json

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"sdk": {
3+
"version": "9.0.0",
4+
"allowPrerelease": true,
5+
"rollForward": "latestMajor"
6+
}
7+
}

‎src/README.MD

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
A modern and efficient unique identifier generator for .NET ecosystem.
2+
3+
A high-performance UUID library designed for modern distributed systems. Features include:
4+
- Thread-safe and high-performance operations
5+
- Time-ordered identifiers for natural sorting
6+
- Enhanced security with cryptographic randomness
7+
- Implicit/explicit conversion operators
8+
- System.Guid compatibility
9+
- Efficient string parsing and formatting
10+
- Multiple encoding formats (Base32, Base64)
11+
- Comparison and equality operations
12+
- Thread-local secure random generation
13+
- Compact 16-byte binary format
14+
- Cross-platform compatibility
15+
- Comprehensive test coverage and benchmarks

‎src/UUID/Resources/UUID.ico

16.6 KB
Binary file not shown.

‎src/UUID/Resources/UUID.png

28.7 KB
Loading

‎src/UUID/UUID.cs

+374
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,374 @@
1+
using System.Security.Cryptography;
2+
3+
namespace UUID
4+
{
5+
/// <summary>
6+
/// UUID represents a unique identifier that combines the best features of GUIDv7, ULID and CUID
7+
/// while providing enhanced security and performance.
8+
/// </summary>
9+
/// <remarks>
10+
/// This implementation provides:
11+
/// - Monotonicity: GUIDs are sortable by creation time
12+
/// - Security: Uses cryptographically secure random numbers
13+
/// - Performance: Optimized for high-performance scenarios
14+
/// - Compatibility: Supports conversion to/from System.Guid
15+
/// </remarks>
16+
public readonly struct UUID(ulong timestamp, ulong random) : IEquatable<UUID>, IComparable<UUID>
17+
{
18+
/// <summary>
19+
/// The size of the UUID in bytes.
20+
/// </summary>
21+
private const int SIZE = 16;
22+
23+
/// <summary>
24+
/// The timestamp component of the UUID.
25+
/// </summary>
26+
private readonly ulong _timestamp = timestamp;
27+
28+
/// <summary>
29+
/// Thread-local random number generator for secure random number generation.
30+
/// </summary>
31+
private static readonly ThreadLocal<RandomNumberGenerator> _rng = new(RandomNumberGenerator.Create);
32+
33+
/// <summary>
34+
/// Creates a new UUID instance with current timestamp.
35+
/// </summary>
36+
public UUID() : this(GenerateTimestamp(), GenerateRandom()) { }
37+
38+
/// <summary>
39+
/// Generates a new UUID using the current timestamp and secure random data.
40+
/// </summary>
41+
/// <returns>A new UUID instance.</returns>
42+
public static UUID New()
43+
{
44+
return new(GenerateTimestamp(), GenerateRandom());
45+
}
46+
47+
/// <summary>
48+
/// Generates a timestamp component for the UUID.
49+
/// </summary>
50+
/// <returns>A 64-bit unsigned integer containing the timestamp and additional random data.</returns>
51+
private static ulong GenerateTimestamp()
52+
{
53+
byte[] bytes = new byte[2];
54+
_rng.Value!.GetBytes(bytes);
55+
56+
long unixMs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
57+
return (((ulong)unixMs & 0x0000_FFFF_FFFF_FFFF) << 16)
58+
| ((ulong)bytes[0] << 8)
59+
| bytes[1];
60+
}
61+
62+
/// <summary>
63+
/// Generates a random component for the UUID.
64+
/// </summary>
65+
/// <returns>A 64-bit random unsigned integer.</returns>
66+
private static ulong GenerateRandom()
67+
{
68+
byte[] bytes = new byte[8];
69+
_rng.Value!.GetBytes(bytes);
70+
return BitConverter.ToUInt64(bytes, 0);
71+
}
72+
73+
/// <summary>
74+
/// Creates a UUID from a string representation.
75+
/// </summary>
76+
/// <param name="input">The string representation of the UUID.</param>
77+
/// <returns>A new UUID instance.</returns>
78+
/// <exception cref="ArgumentNullException">Thrown when input is null.</exception>
79+
/// <exception cref="FormatException">Thrown when input is not in the correct format.</exception>
80+
public static UUID Parse(string input)
81+
{
82+
if (input == null)
83+
{
84+
throw new ArgumentNullException(nameof(input));
85+
}
86+
87+
if (input.Length != 32)
88+
{
89+
throw new FormatException("Input string must be 32 characters long.");
90+
}
91+
92+
ulong timestamp = Convert.ToUInt64(input.Substring(0, 16), 16);
93+
ulong random = Convert.ToUInt64(input.Substring(16), 16);
94+
95+
return new UUID(timestamp, random);
96+
}
97+
98+
/// <summary>
99+
/// Tries to parse a string into a UUID.
100+
/// </summary>
101+
/// <param name="input">The string representation of the UUID.</param>
102+
/// <param name="result">The parsed UUID instance.</param>
103+
/// <returns>true if the string was parsed successfully; otherwise, false.</returns>
104+
public static bool TryParse(string? input, out UUID result)
105+
{
106+
result = default;
107+
108+
// Early return if input is null or not the correct length
109+
if (input == null || input.Length != 32)
110+
{
111+
return false;
112+
}
113+
114+
try
115+
{
116+
ulong timestamp = Convert.ToUInt64(input.Substring(0, 16), 16);
117+
ulong random = Convert.ToUInt64(input.Substring(16), 16);
118+
119+
result = new UUID(timestamp, random);
120+
121+
return true;
122+
}
123+
catch
124+
{
125+
return false;
126+
}
127+
}
128+
129+
/// <summary>
130+
/// Gets the timestamp component of the UUID.
131+
/// </summary>
132+
public DateTimeOffset Time =>
133+
DateTimeOffset.FromUnixTimeMilliseconds((long)(_timestamp >> 16));
134+
135+
/// <summary>
136+
/// Gets the random component of the UUID.
137+
/// </summary>
138+
public ulong Random { get; } = random;
139+
140+
/// <summary>
141+
/// Returns a string representation of the UUID.
142+
/// </summary>
143+
/// <returns>A string representation of the UUID.</returns>
144+
public override string ToString()
145+
{
146+
return $"{_timestamp:x16}{Random:x16}";
147+
}
148+
149+
/// <summary>
150+
/// Returns a Base32 encoded string representation of the UUID.
151+
/// </summary>
152+
/// <returns>A Base32 encoded string representation of the UUID.</returns>
153+
public string ToBase32()
154+
{
155+
const string ENCODING_CHARS = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
156+
char[] result = new char[26];
157+
ulong value = _timestamp;
158+
159+
for (int i = 25; i >= 0; i--)
160+
{
161+
result[i] = ENCODING_CHARS[(int)(value & 0x1F)];
162+
value >>= 5;
163+
if (i == 13)
164+
{
165+
value = Random;
166+
}
167+
}
168+
169+
return new string(result);
170+
}
171+
172+
/// <summary>
173+
/// Returns a Base64 encoded string representation of the UUID.
174+
/// </summary>
175+
/// <returns>A Base64 encoded string representation of the UUID.</returns>
176+
public string ToBase64()
177+
{
178+
byte[] bytes = new byte[SIZE];
179+
TryWriteBytes(bytes);
180+
return Convert.ToBase64String(bytes);
181+
}
182+
183+
/// <summary>
184+
/// Converts the UUID to a byte array.
185+
/// </summary>
186+
/// <returns>A byte array representation of the UUID.</returns>
187+
public byte[] ToByteArray()
188+
{
189+
byte[] bytes = new byte[SIZE];
190+
TryWriteBytes(bytes);
191+
return bytes;
192+
}
193+
194+
/// <summary>
195+
/// Attempts to write the UUID to a byte array.
196+
/// </summary>
197+
/// <param name="destination">The destination byte array.</param>
198+
/// <returns>true if the UUID was written successfully; otherwise, false.</returns>
199+
public bool TryWriteBytes(byte[] destination)
200+
{
201+
if (destination == null || destination.Length < SIZE)
202+
{
203+
return false;
204+
}
205+
206+
BitConverter.GetBytes(_timestamp).CopyTo(destination, 0);
207+
BitConverter.GetBytes(Random).CopyTo(destination, 8);
208+
return true;
209+
}
210+
211+
/// <summary>
212+
/// Attempts to write the UUID to a string buffer.
213+
/// </summary>
214+
/// <param name="destination">The destination string buffer.</param>
215+
/// <returns>true if the UUID was written successfully; otherwise, false.</returns>
216+
public bool TryWriteStringify(char[] destination)
217+
{
218+
if (destination == null || destination.Length < 32)
219+
{
220+
return false;
221+
}
222+
223+
string str = ToString();
224+
str.CopyTo(0, destination, 0, 32);
225+
return true;
226+
}
227+
228+
/// <summary>
229+
/// Converts the UUID to a System.Guid.
230+
/// </summary>
231+
/// <returns>A System.Guid representation of the UUID.</returns>
232+
public Guid ToGuid()
233+
{
234+
byte[] bytes = new byte[SIZE];
235+
TryWriteBytes(bytes);
236+
return new Guid(bytes);
237+
}
238+
239+
/// <summary>
240+
/// Creates a UUID from a System.Guid.
241+
/// </summary>
242+
/// <param name="guid">The System.Guid to convert.</param>
243+
/// <returns>A UUID instance.</returns>
244+
public static UUID FromGuid(Guid guid)
245+
{
246+
byte[] bytes = guid.ToByteArray();
247+
ulong timestamp = BitConverter.ToUInt64(bytes, 0);
248+
ulong random = BitConverter.ToUInt64(bytes, 8);
249+
return new UUID(timestamp, random);
250+
}
251+
252+
/// <summary>
253+
/// Implicit conversion from Guid to UUID.
254+
/// </summary>
255+
/// <param name="guid">The Guid to convert.</param>
256+
/// <returns>A UUID instance.</returns>
257+
/// <remarks>
258+
/// This conversion is implicit because it is always safe and lossless.
259+
/// </remarks>
260+
public static implicit operator UUID(Guid guid)
261+
{
262+
return FromGuid(guid);
263+
}
264+
265+
/// <summary>
266+
/// Explicit conversion from UUID to Guid.
267+
/// </summary>
268+
/// <param name="uuid">The UUID to convert.</param>
269+
/// <returns>A Guid instance.</returns>
270+
/// <remarks>
271+
/// This conversion is explicit to make it clear that you are converting between different UUID formats.
272+
/// </remarks>
273+
public static explicit operator Guid(UUID uuid)
274+
{
275+
return uuid.ToGuid();
276+
}
277+
278+
/// <summary>
279+
/// Determines whether the specified UUID is equal to the current UUID.
280+
/// </summary>
281+
/// <param name="other">The UUID to compare with the current UUID.</param>
282+
/// <returns>true if the specified UUID is equal to the current UUID; otherwise, false.</returns>
283+
public bool Equals(UUID other)
284+
{
285+
return _timestamp == other._timestamp && Random == other.Random;
286+
}
287+
288+
/// <summary>
289+
/// Determines whether the specified object is equal to the current UUID.
290+
/// </summary>
291+
/// <param name="obj">The object to compare with the current UUID.</param>
292+
/// <returns>true if the specified object is a UUID and equal to the current UUID; otherwise, false.</returns>
293+
public override bool Equals(object? obj)
294+
{
295+
return obj is UUID other && Equals(other);
296+
}
297+
298+
/// <summary>
299+
/// Returns a hash code for this UUID.
300+
/// </summary>
301+
/// <returns>A hash code for the current UUID.</returns>
302+
public override int GetHashCode()
303+
{
304+
unchecked
305+
{
306+
return (_timestamp.GetHashCode() * 397) ^ Random.GetHashCode();
307+
}
308+
}
309+
310+
/// <summary>
311+
/// Compares the current UUID with another UUID.
312+
/// </summary>
313+
/// <param name="other">The UUID to compare with this UUID.</param>
314+
/// <returns>
315+
/// A value that indicates the relative order of the UUIDs being compared.
316+
/// Less than zero: This UUID is less than the other UUID.
317+
/// Zero: This UUID is equal to the other UUID.
318+
/// Greater than zero: This UUID is greater than the other UUID.
319+
/// </returns>
320+
public int CompareTo(UUID other)
321+
{
322+
int result = _timestamp.CompareTo(other._timestamp);
323+
return result != 0 ? result : Random.CompareTo(other.Random);
324+
}
325+
326+
/// <summary>
327+
/// Determines whether two UUIDs are equal.
328+
/// </summary>
329+
public static bool operator ==(UUID left, UUID right)
330+
{
331+
return left.Equals(right);
332+
}
333+
334+
/// <summary>
335+
/// Determines whether two UUIDs are not equal.
336+
/// </summary>
337+
public static bool operator !=(UUID left, UUID right)
338+
{
339+
return !left.Equals(right);
340+
}
341+
342+
/// <summary>
343+
/// Determines whether one UUID is less than another UUID.
344+
/// </summary>
345+
public static bool operator <(UUID left, UUID right)
346+
{
347+
return left.CompareTo(right) < 0;
348+
}
349+
350+
/// <summary>
351+
/// Determines whether one UUID is less than or equal to another UUID.
352+
/// </summary>
353+
public static bool operator <=(UUID left, UUID right)
354+
{
355+
return left.CompareTo(right) <= 0;
356+
}
357+
358+
/// <summary>
359+
/// Determines whether one UUID is greater than another UUID.
360+
/// </summary>
361+
public static bool operator >(UUID left, UUID right)
362+
{
363+
return left.CompareTo(right) > 0;
364+
}
365+
366+
/// <summary>
367+
/// Determines whether one UUID is greater than or equal to another UUID.
368+
/// </summary>
369+
public static bool operator >=(UUID left, UUID right)
370+
{
371+
return left.CompareTo(right) >= 0;
372+
}
373+
}
374+
}

‎src/UUID/UUID.csproj

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFrameworks>net48;net6.0;net7.0;net8.0;net9.0;netstandard2.0;netstandard2.1</TargetFrameworks>
5+
<DefaultLanguage>en-GB</DefaultLanguage>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<RootNamespace>UUID</RootNamespace>
8+
<Nullable>enable</Nullable>
9+
</PropertyGroup>
10+
11+
<PropertyGroup>
12+
<ApplicationIcon>Resources\UUID.ico</ApplicationIcon>
13+
<Version>1.0.0.4</Version>
14+
<AssemblyVersion>$(Version)</AssemblyVersion>
15+
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
16+
<Title>UUID</Title>
17+
<PackageId>UUID</PackageId>
18+
<Authors>Taiizor</Authors>
19+
<Copyright>Copyright © $([System.DateTime]::Today.ToString(yyyy)) $(Authors)</Copyright>
20+
<Summary>A modern and efficient unique identifier generator for .NET ecosystem.</Summary>
21+
<Description>A high-performance UUID library designed for modern distributed systems. Features include:
22+
- Thread-safe and high-performance operations
23+
- Time-ordered identifiers for natural sorting
24+
- Enhanced security with cryptographic randomness
25+
- Implicit/explicit conversion operators
26+
- System.Guid compatibility
27+
- Efficient string parsing and formatting
28+
- Multiple encoding formats (Base32, Base64)
29+
- Comparison and equality operations
30+
- Thread-local secure random generation
31+
- Compact 16-byte binary format
32+
- Cross-platform compatibility
33+
- Comprehensive test coverage and benchmarks</Description>
34+
<PackageReadmeFile>README.MD</PackageReadmeFile>
35+
<PackageLicenseFile>LICENSE</PackageLicenseFile>
36+
<PackageLicenseExpression></PackageLicenseExpression>
37+
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
38+
<PackageReleaseNotes>All changes are detailed at https://github.com/Taiizor/UUID/wiki/Changelog.</PackageReleaseNotes>
39+
<PackageTags>uuid id universally unique identifiers identifier distributed scalable generator</PackageTags>
40+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
41+
<!--<DocumentationFile>..\$(Title)\bin$(OutputPath)\$(Configuration)\$(TargetFramework)\$(Title).xml</DocumentationFile>-->
42+
<PackageProjectUrl>https://github.com/Taiizor/UUID</PackageProjectUrl>
43+
<RepositoryType>git</RepositoryType>
44+
<RepositoryUrl>git://github.com/Taiizor/UUID</RepositoryUrl>
45+
<PackageDescription>$(Description)</PackageDescription>
46+
<PackageIcon>UUID.png</PackageIcon>
47+
<Company>$(Authors)</Company>
48+
<Owners>$(Authors)</Owners>
49+
<AnalysisLevel>preview</AnalysisLevel>
50+
<LangVersion>preview</LangVersion>
51+
<NeutralLanguage>$(DefaultLanguage)</NeutralLanguage>
52+
<FileVersion>$(Version)</FileVersion>
53+
<PublishRepositoryUrl>true</PublishRepositoryUrl>
54+
<EmbedUntrackedSources>true</EmbedUntrackedSources>
55+
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
56+
<IncludeSymbols>true</IncludeSymbols>
57+
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
58+
<Configurations>Debug;Release</Configurations>
59+
<NoWarn>1587,1591</NoWarn>
60+
</PropertyGroup>
61+
62+
<ItemGroup>
63+
<PackageReference Include="Microsoft.SourceLink.GitHub">
64+
<Version>8.0.0</Version>
65+
<PrivateAssets>All</PrivateAssets>
66+
</PackageReference>
67+
</ItemGroup>
68+
69+
<ItemGroup>
70+
<None Include="..\README.MD">
71+
<Pack>True</Pack>
72+
<PackagePath></PackagePath>
73+
</None>
74+
<None Include="..\..\LICENSE">
75+
<Pack>True</Pack>
76+
<PackagePath></PackagePath>
77+
</None>
78+
<None Include="Resources\UUID.png">
79+
<Pack>True</Pack>
80+
<PackagePath></PackagePath>
81+
</None>
82+
</ItemGroup>
83+
84+
<ItemGroup>
85+
<Folder Include="Properties\" />
86+
</ItemGroup>
87+
88+
</Project>

‎test/UUID.Tests/UUID.Tests.csproj

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<Nullable>enable</Nullable>
5+
<IsPackable>false</IsPackable>
6+
<LangVersion>preview</LangVersion>
7+
<AnalysisLevel>preview</AnalysisLevel>
8+
<TargetFramework>net9.0</TargetFramework>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="xunit" Version="2.9.2" />
13+
<PackageReference Include="System.Net.Http" Version="4.3.4" />
14+
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
15+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
16+
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.0">
17+
<PrivateAssets>all</PrivateAssets>
18+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
19+
</PackageReference>
20+
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
21+
</ItemGroup>
22+
23+
<ItemGroup>
24+
<ProjectReference Include="..\..\src\UUID\UUID.csproj" />
25+
</ItemGroup>
26+
27+
</Project>

‎test/UUID.Tests/UUIDTests.cs

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Threading.Tasks;
4+
using Xunit;
5+
6+
namespace UUID.Tests
7+
{
8+
public class UUIDTests
9+
{
10+
[Fact]
11+
public void New_ShouldGenerateUniqueValues()
12+
{
13+
HashSet<UUID> set = new();
14+
for (int i = 0; i < 10000; i++)
15+
{
16+
UUID uuid = UUID.New();
17+
Assert.True(set.Add(uuid), "Generated UUID is not unique");
18+
}
19+
}
20+
21+
[Fact]
22+
public void New_ShouldHaveMonotonicTimestamps()
23+
{
24+
UUID previous = UUID.New();
25+
for (int i = 0; i < 1000; i++)
26+
{
27+
UUID current = UUID.New();
28+
Assert.True(current.Time >= previous.Time);
29+
previous = current;
30+
}
31+
}
32+
33+
[Fact]
34+
public void Parse_ShouldHandleValidInput()
35+
{
36+
UUID uuid = UUID.New();
37+
string str = uuid.ToString();
38+
UUID parsed = UUID.Parse(str);
39+
Assert.Equal(uuid, parsed);
40+
}
41+
42+
[Fact]
43+
public void Parse_ShouldThrowOnInvalidInput()
44+
{
45+
Assert.Throws<ArgumentNullException>(() => UUID.Parse(null!));
46+
Assert.Throws<FormatException>(() => UUID.Parse("invalid"));
47+
}
48+
49+
[Fact]
50+
public void TryParse_ShouldHandleValidAndInvalidInput()
51+
{
52+
UUID uuid = UUID.New();
53+
string str = uuid.ToString();
54+
55+
Assert.True(UUID.TryParse(str, out UUID parsed));
56+
Assert.Equal(uuid, parsed);
57+
58+
Assert.False(UUID.TryParse(null, out _));
59+
Assert.False(UUID.TryParse("invalid", out _));
60+
}
61+
62+
[Fact]
63+
public void Base32_ShouldBeReversible()
64+
{
65+
UUID uuid = UUID.New();
66+
string base32 = uuid.ToBase32();
67+
68+
Assert.Equal(26, base32.Length);
69+
Assert.Matches("^[0-9A-Z]{26}$", base32);
70+
}
71+
72+
[Fact]
73+
public void Base64_AndByteArray_ShouldBeReversible()
74+
{
75+
UUID uuid = UUID.New();
76+
byte[] bytes = uuid.ToByteArray();
77+
string base64 = uuid.ToBase64();
78+
79+
Assert.Equal(16, bytes.Length);
80+
Assert.Equal(24, base64.Length);
81+
82+
byte[] destination = new byte[16];
83+
Assert.True(uuid.TryWriteBytes(destination));
84+
Assert.Equal(bytes, destination);
85+
}
86+
87+
[Fact]
88+
public void Guid_Conversion_ShouldBeReversible()
89+
{
90+
UUID uuid = UUID.New();
91+
Guid guid = uuid.ToGuid();
92+
UUID convertedBack = UUID.FromGuid(guid);
93+
94+
Assert.Equal(uuid, convertedBack);
95+
96+
// Operator tests
97+
UUID fromImplicit = guid;
98+
Guid toExplicit = (Guid)uuid;
99+
100+
Assert.Equal(uuid, fromImplicit);
101+
Assert.Equal(guid, toExplicit);
102+
}
103+
104+
[Fact]
105+
public async Task New_ShouldBeThreadSafe()
106+
{
107+
HashSet<UUID> set = new();
108+
List<Task> tasks = new();
109+
object lockObj = new();
110+
111+
for (int i = 0; i < 10; i++)
112+
{
113+
tasks.Add(Task.Run(() =>
114+
{
115+
for (int j = 0; j < 1000; j++)
116+
{
117+
UUID uuid = UUID.New();
118+
lock (lockObj)
119+
{
120+
Assert.True(set.Add(uuid), "UUID collision detected in multi-threaded scenario");
121+
}
122+
}
123+
}));
124+
}
125+
126+
await Task.WhenAll(tasks);
127+
}
128+
}
129+
}

0 commit comments

Comments
 (0)
Please sign in to comment.