< Summary

Class:Towel.SLazyNoCatch<T>
Assembly:Towel
File(s):File 1: /home/runner/work/Towel/Towel/Sources/Towel/Lazy.cs
Covered lines:51
Uncovered lines:0
Coverable lines:51
Total lines:1567
Line coverage:100% (51 of 51)
Covered branches:22
Total branches:22
Branch coverage:100% (22 of 22)

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
File 1: get_IsValueCreated()100%4100%
File 1: get_Value()100%2100%
File 1: get_ThreadSafety()100%1100%
File 1: get_IsCachingExceptions()100%1100%
File 1: get_IsStructCopySafe()100%1100%
File 1: .ctor(...)100%1100%
File 1: .ctor(...)100%2100%
File 1: op_Implicit(...)100%1100%
File 1: op_Implicit(...)100%1100%
File 1: Equals(...)100%10100%
File 1: ToString()100%2100%
File 1: GetHashCode()100%2100%
File 1: op_Equality(...)100%1100%
File 1: op_Inequality(...)100%1100%

File(s)

/home/runner/work/Towel/Towel/Sources/Towel/Lazy.cs

#LineLine coverage
 1using System.Threading;
 2
 3namespace Towel;
 4#region ILazy<T>
 5
 6/// <summary>Provides support for lazy initialization.</summary>
 7/// <typeparam name="T">The type of value that is being lazily initialized.</typeparam>
 8public interface ILazy<T>
 9{
 10  /// <summary>The pattern of thread safety this lazy is using.</summary>
 11  LazyThreadSafetyMode ThreadSafety { get; }
 12  /// <summary>Gets the lazily initialized value.</summary>
 13  T Value { get; }
 14  /// <summary>True if <see cref="Value"/> has been initialized.</summary>
 15  bool IsValueCreated { get; }
 16  /// <summary>True if exceptions thrown by the factory delegate are being cached.</summary>
 17  bool IsCachingExceptions { get; }
 18  /// <summary>True if the lazy is safe from struct copies.</summary>
 19  bool IsStructCopySafe { get; }
 20}
 21
 22#endregion
 23
 24#region SLazyReference<T>
 25
 26internal class SLazyReference<T>
 27{
 28  internal Func<T>? _func;
 29  internal T? _value;
 30
 31  internal SLazyReference(Func<T> func) => _func = func;
 32
 33  internal T GetValueSafe()
 34  {
 35    lock (this)
 36    {
 37      if (_func is not null)
 38      {
 39        try
 40        {
 41          _value = _func();
 42          _func = null;
 43        }
 44        catch (Exception exception)
 45        {
 46          _func = () => throw exception;
 47          throw;
 48        }
 49      }
 50    }
 51    return _value!;
 52  }
 53
 54  internal T GetValuePublicationLock()
 55  {
 56    Func<T>? func = _func;
 57    if (func is not null)
 58    {
 59      try
 60      {
 61        T value = func();
 62        lock (this)
 63        {
 64          if (_func is not null)
 65          {
 66            if (ReferenceEquals(_func, func))
 67            {
 68              _value = value;
 69              _func = null;
 70            }
 71            else
 72            {
 73              _ = _func();
 74            }
 75          }
 76        }
 77      }
 78      catch (Exception exception)
 79      {
 80        lock (this)
 81        {
 82          if (_func is not null)
 83          {
 84            if (ReferenceEquals(_func, func))
 85            {
 86              _func = () => throw exception;
 87              throw;
 88            }
 89            else
 90            {
 91              _ = _func();
 92            }
 93          }
 94        }
 95      }
 96    }
 97    return _value!;
 98  }
 99
 100  internal T GetValuePublicationLockNoCatch()
 101  {
 102    Func<T>? func = _func;
 103    if (func is not null)
 104    {
 105      T value = func();
 106      lock (this)
 107      {
 108        if (_func is not null)
 109        {
 110          _value = value;
 111          _func = null;
 112        }
 113      }
 114    }
 115    return _value!;
 116  }
 117
 118  internal T GetValueNoLock()
 119  {
 120    if (_func is not null)
 121    {
 122      try
 123      {
 124        _value = _func();
 125        _func = null;
 126      }
 127      catch (Exception exception)
 128      {
 129        _func = () => throw exception;
 130        throw;
 131      }
 132    }
 133    return _value!;
 134  }
 135
 136  internal T GetValueNoCatch()
 137  {
 138    lock (this)
 139    {
 140      if (_func is not null)
 141      {
 142        _value = _func();
 143        _func = null;
 144      }
 145    }
 146    return _value!;
 147  }
 148
 149  internal T GetValueNoLockNoCatch()
 150  {
 151    if (_func is not null)
 152    {
 153      _value = _func();
 154      _func = null;
 155    }
 156    return _value!;
 157  }
 158}
 159
 160#endregion
 161
 162#region SLazy<T>
 163
 164/// <summary>Provides support for lazy initialization.</summary>
 165/// <typeparam name="T">The type of value that is being lazily initialized.</typeparam>
 166public struct SLazy<T> : ILazy<T>
 167{
 168  internal SLazyReference<T>? _reference;
 169  internal T? _value;
 170
 171  /// <inheritdoc />
 172  public bool IsValueCreated
 173  {
 174    get
 175    {
 176      SLazyReference<T>? reference = _reference;
 177      if (reference is not null)
 178      {
 179        if (reference._func is null)
 180        {
 181          _value = reference._value;
 182          _reference = null;
 183          return true;
 184        }
 185        return false;
 186      }
 187      return true;
 188    }
 189  }
 190
 191  /// <inheritdoc />
 192  public T Value
 193  {
 194    get
 195    {
 196      if (_reference is not null)
 197      {
 198        _value = _reference.GetValueSafe();
 199        _reference = null;
 200      }
 201      return _value!;
 202    }
 203  }
 204
 205  /// <inheritdoc />
 206  public LazyThreadSafetyMode ThreadSafety => LazyThreadSafetyMode.ExecutionAndPublication;
 207
 208  /// <inheritdoc />
 209  public bool IsCachingExceptions => true;
 210
 211  /// <inheritdoc />
 212  public bool IsStructCopySafe => true;
 213
 214  /// <summary>Constructs a new <see cref="SLazy{T}"/> from a <typeparamref name="T"/>.</summary>
 215  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 216  public SLazy(T value)
 217  {
 218    _reference = null;
 219    _value = value;
 220  }
 221
 222  /// <summary>Constructs a new <see cref="SLazy{T}"/> from a <see cref="Func{T}"/>.</summary>
 223  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 224  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 225  public SLazy(Func<T> func)
 226  {
 227    if (func is null) throw new ArgumentNullException(nameof(func));
 228    _value = default;
 229    _reference = new(func);
 230  }
 231
 232  /// <summary>Constructs a new <see cref="SLazy{T}"/> from a <see cref="Func{T}"/>.</summary>
 233  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 234  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 235  public static implicit operator SLazy<T>(Func<T> func) => new(func);
 236
 237  /// <summary>Constructs a new <see cref="SLazy{T}"/> from a <typeparamref name="T"/>.</summary>
 238  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 239  public static implicit operator SLazy<T>(T value) => new(value);
 240
 241  /// <summary>Checks for equality between <see cref="Value"/> and <paramref name="obj"/>.</summary>
 242  /// <param name="obj">The value to compare to <see cref="Value"/>.</param>
 243  /// <returns>True if <see cref="Value"/> and <paramref name="obj"/> are equal or False if not.</returns>
 244  public override bool Equals(object? obj)
 245  {
 246    if (obj is SLazy<T> slazy)
 247    {
 248      obj = slazy.Value;
 249    }
 250    return (Value, obj) switch
 251    {
 252      (null, null) => true,
 253      (_,    null) => false,
 254      (null,    _) => false,
 255      _ => Value!.Equals(obj),
 256    };
 257  }
 258
 259  /// <summary>Returns a string that represents <see cref="Value"/>.</summary>
 260  /// <returns>A string that represents <see cref="Value"/></returns>
 261  public override string? ToString() => Value?.ToString();
 262
 263  /// <summary>Gets the hash code of <see cref="Value"/>.</summary>
 264  /// <returns>The hash code of <see cref="Value"/>.</returns>
 265  public override int GetHashCode() => Value?.GetHashCode() ?? default;
 266
 267  /// <summary>Checks for equality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 268  /// <param name="left">The first value of the equality check.</param>
 269  /// <param name="right">The second value of the equality check.</param>
 270  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are equal or False if not.</returns>
 271  public static bool operator ==(SLazy<T> left, SLazy<T> right) => left.Equals(right);
 272
 273  /// <summary>Checks for inequality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 274  /// <param name="left">The first value of the inequality check.</param>
 275  /// <param name="right">The second value of the inequality check.</param>
 276  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are not equal or False if not.</returns>
 277  public static bool operator !=(SLazy<T> left, SLazy<T> right) => !(left == right);
 278}
 279
 280#endregion
 281
 282#region SLazyNoCatch<T>
 283
 284/// <summary>Provides support for lazy initialization.</summary>
 285/// <typeparam name="T">The type of value that is being lazily initialized.</typeparam>
 286public struct SLazyNoCatch<T> : ILazy<T>
 287{
 288  internal SLazyReference<T>? _reference;
 289  internal T? _value;
 290
 291  /// <inheritdoc />
 292  public bool IsValueCreated
 293  {
 294    get
 9295    {
 9296      SLazyReference<T>? reference = _reference;
 9297      if (reference is not null)
 5298      {
 5299        if (reference._func is null)
 1300        {
 1301          _value = reference._value;
 1302          _reference = null;
 1303          return true;
 304        }
 4305        return false;
 306      }
 4307      return true;
 9308    }
 309  }
 310
 311  /// <inheritdoc />
 312  public T Value
 313  {
 314    get
 73315    {
 73316      if (_reference is not null)
 29317      {
 29318        _value = _reference.GetValueNoCatch();
 25319        _reference = null;
 25320      }
 69321      return _value!;
 69322    }
 323  }
 324
 325  /// <inheritdoc />
 2326  public LazyThreadSafetyMode ThreadSafety => LazyThreadSafetyMode.ExecutionAndPublication;
 327
 328  /// <inheritdoc />
 1329  public bool IsCachingExceptions => false;
 330
 331  /// <inheritdoc />
 1332  public bool IsStructCopySafe => true;
 333
 334  /// <summary>Constructs a new <see cref="SLazyNoCatch{T}"/> from a <typeparamref name="T"/>.</summary>
 335  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 336  public SLazyNoCatch(T value)
 19337  {
 19338    _reference = null;
 19339    _value = value;
 19340  }
 341
 342  /// <summary>Constructs a new <see cref="SLazyNoCatch{T}"/> from a <see cref="Func{T}"/>.</summary>
 343  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 344  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 345  public SLazyNoCatch(Func<T> func)
 25346  {
 28347    if (func is null) throw new ArgumentNullException(nameof(func));
 22348    _value = default;
 22349    _reference = new(func);
 22350  }
 351
 352  /// <summary>Constructs a new <see cref="SLazyNoCatch{T}"/> from a <see cref="Func{T}"/>.</summary>
 353  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 354  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 25355  public static implicit operator SLazyNoCatch<T>(Func<T> func) => new(func);
 356
 357  /// <summary>Constructs a new <see cref="SLazyNoCatch{T}"/> from a <typeparamref name="T"/>.</summary>
 358  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 19359  public static implicit operator SLazyNoCatch<T>(T value) => new(value);
 360
 361  /// <summary>Checks for equality between <see cref="Value"/> and <paramref name="obj"/>.</summary>
 362  /// <param name="obj">The value to compare to <see cref="Value"/>.</param>
 363  /// <returns>True if <see cref="Value"/> and <paramref name="obj"/> are equal or False if not.</returns>
 364  public override bool Equals(object? obj)
 18365  {
 18366    if (obj is SLazyNoCatch<T> slazy)
 13367    {
 13368      obj = slazy.Value;
 13369    }
 18370    return (Value, obj) switch
 18371    {
 3372      (null, null) => true,
 1373      (_,    null) => false,
 1374      (null,    _) => false,
 13375      _ => Value!.Equals(obj),
 18376    };
 18377  }
 378
 379  /// <summary>Returns a string that represents <see cref="Value"/>.</summary>
 380  /// <returns>A string that represents <see cref="Value"/></returns>
 5381  public override string? ToString() => Value?.ToString();
 382
 383  /// <summary>Gets the hash code of <see cref="Value"/>.</summary>
 384  /// <returns>The hash code of <see cref="Value"/>.</returns>
 7385  public override int GetHashCode() => Value?.GetHashCode() ?? default;
 386
 387  /// <summary>Checks for equality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 388  /// <param name="left">The first value of the equality check.</param>
 389  /// <param name="right">The second value of the equality check.</param>
 390  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are equal or False if not.</returns>
 2391  public static bool operator ==(SLazyNoCatch<T> left, SLazyNoCatch<T> right) => left.Equals(right);
 392
 393  /// <summary>Checks for inequality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 394  /// <param name="left">The first value of the inequality check.</param>
 395  /// <param name="right">The second value of the inequality check.</param>
 396  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are not equal or False if not.</returns>
 1397  public static bool operator !=(SLazyNoCatch<T> left, SLazyNoCatch<T> right) => !(left == right);
 398}
 399
 400#endregion
 401
 402#region SLazyNoLock<T>
 403
 404/// <summary>Provides support for lazy initialization.</summary>
 405/// <typeparam name="T">The type of value that is being lazily initialized.</typeparam>
 406public struct SLazyNoLock<T> : ILazy<T>
 407{
 408  internal SLazyReference<T>? _reference;
 409  internal T? _value;
 410
 411  /// <inheritdoc />
 412  public bool IsValueCreated
 413  {
 414    get
 415    {
 416      SLazyReference<T>? reference = _reference;
 417      if (reference is not null)
 418      {
 419        if (reference._func is null)
 420        {
 421          _value = reference._value;
 422          _reference = null;
 423          return true;
 424        }
 425        return false;
 426      }
 427      return true;
 428    }
 429  }
 430
 431  /// <inheritdoc />
 432  public T Value
 433  {
 434    get
 435    {
 436      if (_reference is not null)
 437      {
 438        _value = _reference.GetValueNoLock();
 439        _reference = null;
 440      }
 441      return _value!;
 442    }
 443  }
 444
 445  /// <inheritdoc />
 446  public LazyThreadSafetyMode ThreadSafety => LazyThreadSafetyMode.None;
 447
 448  /// <inheritdoc />
 449  public bool IsCachingExceptions => true;
 450
 451  /// <inheritdoc />
 452  public bool IsStructCopySafe => true;
 453
 454  /// <summary>Constructs a new <see cref="SLazyNoLock{T}"/> from a <typeparamref name="T"/>.</summary>
 455  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 456  public SLazyNoLock(T value)
 457  {
 458    _reference = null;
 459    _value = value;
 460  }
 461
 462  /// <summary>Constructs a new <see cref="SLazyNoLock{T}"/> from a <see cref="Func{T}"/>.</summary>
 463  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 464  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 465  public SLazyNoLock(Func<T> func)
 466  {
 467    if (func is null) throw new ArgumentNullException(nameof(func));
 468    _value = default;
 469    _reference = new(func);
 470  }
 471
 472  /// <summary>Constructs a new <see cref="SLazyNoLock{T}"/> from a <see cref="Func{T}"/>.</summary>
 473  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 474  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 475  public static implicit operator SLazyNoLock<T>(Func<T> func) => new(func);
 476
 477  /// <summary>Constructs a new <see cref="SLazyNoLock{T}"/> from a <typeparamref name="T"/>.</summary>
 478  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 479  public static implicit operator SLazyNoLock<T>(T value) => new(value);
 480
 481  /// <summary>Checks for equality between <see cref="Value"/> and <paramref name="obj"/>.</summary>
 482  /// <param name="obj">The value to compare to <see cref="Value"/>.</param>
 483  /// <returns>True if <see cref="Value"/> and <paramref name="obj"/> are equal or False if not.</returns>
 484  public override bool Equals(object? obj)
 485  {
 486    if (obj is SLazyNoLock<T> slazy)
 487    {
 488      obj = slazy.Value;
 489    }
 490    return (Value, obj) switch
 491    {
 492      (null, null) => true,
 493      (_,    null) => false,
 494      (null,    _) => false,
 495      _ => Value!.Equals(obj),
 496    };
 497  }
 498
 499  /// <summary>Returns a string that represents <see cref="Value"/>.</summary>
 500  /// <returns>A string that represents <see cref="Value"/></returns>
 501  public override string? ToString() => Value?.ToString();
 502
 503  /// <summary>Gets the hash code of <see cref="Value"/>.</summary>
 504  /// <returns>The hash code of <see cref="Value"/>.</returns>
 505  public override int GetHashCode() => Value?.GetHashCode() ?? default;
 506
 507  /// <summary>Checks for equality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 508  /// <param name="left">The first value of the equality check.</param>
 509  /// <param name="right">The second value of the equality check.</param>
 510  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are equal or False if not.</returns>
 511  public static bool operator ==(SLazyNoLock<T> left, SLazyNoLock<T> right) => left.Equals(right);
 512
 513  /// <summary>Checks for inequality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 514  /// <param name="left">The first value of the inequality check.</param>
 515  /// <param name="right">The second value of the inequality check.</param>
 516  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are not equal or False if not.</returns>
 517  public static bool operator !=(SLazyNoLock<T> left, SLazyNoLock<T> right) => !(left == right);
 518}
 519
 520#endregion
 521
 522#region SLazyNoLockNoCatch<T>
 523
 524/// <summary>Provides support for lazy initialization.</summary>
 525/// <typeparam name="T">The type of value that is being lazily initialized.</typeparam>
 526public struct SLazyNoLockNoCatch<T> : ILazy<T>
 527{
 528  internal SLazyReference<T>? _reference;
 529  internal T? _value;
 530
 531  /// <inheritdoc />
 532  public bool IsValueCreated
 533  {
 534    get
 535    {
 536      SLazyReference<T>? reference = _reference;
 537      if (reference is not null)
 538      {
 539        if (reference._func is null)
 540        {
 541          _value = reference._value;
 542          _reference = null;
 543          return true;
 544        }
 545        return false;
 546      }
 547      return true;
 548    }
 549  }
 550
 551  /// <inheritdoc />
 552  public T Value
 553  {
 554    get
 555    {
 556      if (_reference is not null)
 557      {
 558        _value = _reference.GetValueNoLockNoCatch();
 559        _reference = null;
 560      }
 561      return _value!;
 562    }
 563  }
 564
 565  /// <inheritdoc />
 566  public LazyThreadSafetyMode ThreadSafety => LazyThreadSafetyMode.None;
 567
 568  /// <inheritdoc />
 569  public bool IsCachingExceptions => false;
 570
 571  /// <inheritdoc />
 572  public bool IsStructCopySafe => true;
 573
 574  /// <summary>Constructs a new <see cref="SLazyNoLockNoCatch{T}"/> from a <typeparamref name="T"/>.</summary>
 575  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 576  public SLazyNoLockNoCatch(T value)
 577  {
 578    _reference = null;
 579    _value = value;
 580  }
 581
 582  /// <summary>Constructs a new <see cref="SLazyNoLockNoCatch{T}"/> from a <see cref="Func{T}"/>.</summary>
 583  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 584  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 585  public SLazyNoLockNoCatch(Func<T> func)
 586  {
 587    if (func is null) throw new ArgumentNullException(nameof(func));
 588    _value = default;
 589    _reference = new(func);
 590  }
 591
 592  /// <summary>Constructs a new <see cref="SLazyNoLockNoCatch{T}"/> from a <see cref="Func{T}"/>.</summary>
 593  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 594  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 595  public static implicit operator SLazyNoLockNoCatch<T>(Func<T> func) => new(func);
 596
 597  /// <summary>Constructs a new <see cref="SLazyNoCatch{T}"/> from a <typeparamref name="T"/>.</summary>
 598  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 599  public static implicit operator SLazyNoLockNoCatch<T>(T value) => new(value);
 600
 601  /// <summary>Checks for equality between <see cref="Value"/> and <paramref name="obj"/>.</summary>
 602  /// <param name="obj">The value to compare to <see cref="Value"/>.</param>
 603  /// <returns>True if <see cref="Value"/> and <paramref name="obj"/> are equal or False if not.</returns>
 604  public override bool Equals(object? obj)
 605  {
 606    if (obj is SLazyNoLockNoCatch<T> slazy)
 607    {
 608      obj = slazy.Value;
 609    }
 610    return (Value, obj) switch
 611    {
 612      (null, null) => true,
 613      (_,    null) => false,
 614      (null,    _) => false,
 615      _ => Value!.Equals(obj),
 616    };
 617  }
 618
 619  /// <summary>Returns a string that represents <see cref="Value"/>.</summary>
 620  /// <returns>A string that represents <see cref="Value"/></returns>
 621  public override string? ToString() => Value?.ToString();
 622
 623  /// <summary>Gets the hash code of <see cref="Value"/>.</summary>
 624  /// <returns>The hash code of <see cref="Value"/>.</returns>
 625  public override int GetHashCode() => Value?.GetHashCode() ?? default;
 626
 627  /// <summary>Checks for equality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 628  /// <param name="left">The first value of the equality check.</param>
 629  /// <param name="right">The second value of the equality check.</param>
 630  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are equal or False if not.</returns>
 631  public static bool operator ==(SLazyNoLockNoCatch<T> left, SLazyNoLockNoCatch<T> right) => left.Equals(right);
 632
 633  /// <summary>Checks for inequality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 634  /// <param name="left">The first value of the inequality check.</param>
 635  /// <param name="right">The second value of the inequality check.</param>
 636  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are not equal or False if not.</returns>
 637  public static bool operator !=(SLazyNoLockNoCatch<T> left, SLazyNoLockNoCatch<T> right) => !(left == right);
 638}
 639
 640#endregion
 641
 642#region SLazyPublicationLock<T>
 643
 644/// <summary>Provides support for lazy initialization.</summary>
 645/// <typeparam name="T">The type of value that is being lazily initialized.</typeparam>
 646public struct SLazyPublicationLock<T> : ILazy<T>
 647{
 648  internal SLazyReference<T>? _reference;
 649  internal T? _value;
 650
 651  /// <inheritdoc />
 652  public bool IsValueCreated
 653  {
 654    get
 655    {
 656      SLazyReference<T>? reference = _reference;
 657      if (reference is not null)
 658      {
 659        if (reference._func is null)
 660        {
 661          _value = reference._value;
 662          _reference = null;
 663          return true;
 664        }
 665        return false;
 666      }
 667      return true;
 668    }
 669  }
 670
 671  /// <inheritdoc />
 672  public T Value
 673  {
 674    get
 675    {
 676      if (_reference is not null)
 677      {
 678        _value = _reference.GetValuePublicationLock();
 679        _reference = null;
 680      }
 681      return _value!;
 682    }
 683  }
 684
 685  /// <inheritdoc />
 686  public LazyThreadSafetyMode ThreadSafety => LazyThreadSafetyMode.PublicationOnly;
 687
 688  /// <inheritdoc />
 689  public bool IsCachingExceptions => true;
 690
 691  /// <inheritdoc />
 692  public bool IsStructCopySafe => true;
 693
 694  /// <summary>Constructs a new <see cref="SLazyPublicationLock{T}"/> from a <typeparamref name="T"/>.</summary>
 695  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 696  public SLazyPublicationLock(T value)
 697  {
 698    _reference = null;
 699    _value = value;
 700  }
 701
 702  /// <summary>Constructs a new <see cref="SLazyPublicationLock{T}"/> from a <see cref="Func{T}"/>.</summary>
 703  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 704  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 705  public SLazyPublicationLock(Func<T> func)
 706  {
 707    if (func is null) throw new ArgumentNullException(nameof(func));
 708    _value = default;
 709    _reference = new(func);
 710  }
 711
 712  /// <summary>Constructs a new <see cref="SLazyPublicationLock{T}"/> from a <see cref="Func{T}"/>.</summary>
 713  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 714  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 715  public static implicit operator SLazyPublicationLock<T>(Func<T> func) => new(func);
 716
 717  /// <summary>Constructs a new <see cref="SLazyPublicationLock{T}"/> from a <typeparamref name="T"/>.</summary>
 718  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 719  public static implicit operator SLazyPublicationLock<T>(T value) => new(value);
 720
 721  /// <summary>Checks for equality between <see cref="Value"/> and <paramref name="obj"/>.</summary>
 722  /// <param name="obj">The value to compare to <see cref="Value"/>.</param>
 723  /// <returns>True if <see cref="Value"/> and <paramref name="obj"/> are equal or False if not.</returns>
 724  public override bool Equals(object? obj)
 725  {
 726    if (obj is SLazyPublicationLock<T> slazy)
 727    {
 728      obj = slazy.Value;
 729    }
 730    return (Value, obj) switch
 731    {
 732      (null, null) => true,
 733      (_,    null) => false,
 734      (null,    _) => false,
 735      _ => Value!.Equals(obj),
 736    };
 737  }
 738
 739  /// <summary>Returns a string that represents <see cref="Value"/>.</summary>
 740  /// <returns>A string that represents <see cref="Value"/></returns>
 741  public override string? ToString() => Value?.ToString();
 742
 743  /// <summary>Gets the hash code of <see cref="Value"/>.</summary>
 744  /// <returns>The hash code of <see cref="Value"/>.</returns>
 745  public override int GetHashCode() => Value?.GetHashCode() ?? default;
 746
 747  /// <summary>Checks for equality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 748  /// <param name="left">The first value of the equality check.</param>
 749  /// <param name="right">The second value of the equality check.</param>
 750  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are equal or False if not.</returns>
 751  public static bool operator ==(SLazyPublicationLock<T> left, SLazyPublicationLock<T> right) => left.Equals(right);
 752
 753  /// <summary>Checks for inequality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 754  /// <param name="left">The first value of the inequality check.</param>
 755  /// <param name="right">The second value of the inequality check.</param>
 756  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are not equal or False if not.</returns>
 757  public static bool operator !=(SLazyPublicationLock<T> left, SLazyPublicationLock<T> right) => !(left == right);
 758}
 759
 760#endregion
 761
 762#region SLazyPublicationLockNoCatch<T>
 763
 764/// <summary>Provides support for lazy initialization.</summary>
 765/// <typeparam name="T">The type of value that is being lazily initialized.</typeparam>
 766public struct SLazyPublicationLockNoCatch<T> : ILazy<T>
 767{
 768  internal SLazyReference<T>? _reference;
 769  internal T? _value;
 770
 771  /// <inheritdoc />
 772  public bool IsValueCreated
 773  {
 774    get
 775    {
 776      SLazyReference<T>? reference = _reference;
 777      if (reference is not null)
 778      {
 779        if (reference._func is null)
 780        {
 781          _value = reference._value;
 782          _reference = null;
 783          return true;
 784        }
 785        return false;
 786      }
 787      return true;
 788    }
 789  }
 790
 791  /// <inheritdoc />
 792  public T Value
 793  {
 794    get
 795    {
 796      if (_reference is not null)
 797      {
 798        _value = _reference.GetValuePublicationLockNoCatch();
 799        _reference = null;
 800      }
 801      return _value!;
 802    }
 803  }
 804
 805  /// <inheritdoc />
 806  public LazyThreadSafetyMode ThreadSafety => LazyThreadSafetyMode.PublicationOnly;
 807
 808  /// <inheritdoc />
 809  public bool IsCachingExceptions => false;
 810
 811  /// <inheritdoc />
 812  public bool IsStructCopySafe => true;
 813
 814  /// <summary>Constructs a new <see cref="SLazyPublicationLockNoCatch{T}"/> from a <typeparamref name="T"/>.</summary>
 815  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 816  public SLazyPublicationLockNoCatch(T value)
 817  {
 818    _reference = null;
 819    _value = value;
 820  }
 821
 822  /// <summary>Constructs a new <see cref="SLazyPublicationLockNoCatch{T}"/> from a <see cref="Func{T}"/>.</summary>
 823  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 824  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 825  public SLazyPublicationLockNoCatch(Func<T> func)
 826  {
 827    if (func is null) throw new ArgumentNullException(nameof(func));
 828    _value = default;
 829    _reference = new(func);
 830  }
 831
 832  /// <summary>Constructs a new <see cref="SLazyPublicationLockNoCatch{T}"/> from a <see cref="Func{T}"/>.</summary>
 833  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 834  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 835  public static implicit operator SLazyPublicationLockNoCatch<T>(Func<T> func) => new(func);
 836
 837  /// <summary>Constructs a new <see cref="SLazyNoCatch{T}"/> from a <typeparamref name="T"/>.</summary>
 838  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 839  public static implicit operator SLazyPublicationLockNoCatch<T>(T value) => new(value);
 840
 841  /// <summary>Checks for equality between <see cref="Value"/> and <paramref name="obj"/>.</summary>
 842  /// <param name="obj">The value to compare to <see cref="Value"/>.</param>
 843  /// <returns>True if <see cref="Value"/> and <paramref name="obj"/> are equal or False if not.</returns>
 844  public override bool Equals(object? obj)
 845  {
 846    if (obj is SLazyPublicationLockNoCatch<T> slazy)
 847    {
 848      obj = slazy.Value;
 849    }
 850    return (Value, obj) switch
 851    {
 852      (null, null) => true,
 853      (_,    null) => false,
 854      (null,    _) => false,
 855      _ => Value!.Equals(obj),
 856    };
 857  }
 858
 859  /// <summary>Returns a string that represents <see cref="Value"/>.</summary>
 860  /// <returns>A string that represents <see cref="Value"/></returns>
 861  public override string? ToString() => Value?.ToString();
 862
 863  /// <summary>Gets the hash code of <see cref="Value"/>.</summary>
 864  /// <returns>The hash code of <see cref="Value"/>.</returns>
 865  public override int GetHashCode() => Value?.GetHashCode() ?? default;
 866
 867  /// <summary>Checks for equality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 868  /// <param name="left">The first value of the equality check.</param>
 869  /// <param name="right">The second value of the equality check.</param>
 870  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are equal or False if not.</returns>
 871  public static bool operator ==(SLazyPublicationLockNoCatch<T> left, SLazyPublicationLockNoCatch<T> right) => left.Equa
 872
 873  /// <summary>Checks for inequality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 874  /// <param name="left">The first value of the inequality check.</param>
 875  /// <param name="right">The second value of the inequality check.</param>
 876  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are not equal or False if not.</returns>
 877  public static bool operator !=(SLazyPublicationLockNoCatch<T> left, SLazyPublicationLockNoCatch<T> right) => !(left ==
 878}
 879
 880#endregion
 881
 882#region ValueLazy<T>
 883
 884/// <summary>Provides support for lazy initialization.</summary>
 885/// <typeparam name="T">The type of value that is being lazily initialized.</typeparam>
 886public struct ValueLazy<T> : ILazy<T>
 887{
 888  internal Func<T>? _func;
 889  internal T? _value;
 890
 891  /// <inheritdoc />
 892  public bool IsValueCreated => _func is null;
 893
 894  /// <inheritdoc />
 895  public T Value => _func is null ? _value! : GetValueSafe();
 896
 897  /// <inheritdoc />
 898  public LazyThreadSafetyMode ThreadSafety => LazyThreadSafetyMode.ExecutionAndPublication;
 899
 900  /// <inheritdoc />
 901  public bool IsCachingExceptions => true;
 902
 903  /// <inheritdoc />
 904  public bool IsStructCopySafe => false;
 905
 906  internal T GetValueSafe()
 907  {
 908    Func<T>? func = _func;
 909    if (func is not null)
 910    {
 911      lock (func)
 912      {
 913        if (_func is not null)
 914        {
 915          try
 916          {
 917            _value = _func();
 918            _func = null;
 919          }
 920          catch (Exception exception)
 921          {
 922            _func = () => throw exception;
 923            throw;
 924          }
 925        }
 926      }
 927    }
 928    return _value!;
 929  }
 930
 931  /// <summary>Constructs a new <see cref="ValueLazy{T}"/> from a <typeparamref name="T"/>.</summary>
 932  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 933  public ValueLazy(T value)
 934  {
 935    _func = null;
 936    _value = value;
 937  }
 938
 939  /// <summary>Constructs a new <see cref="ValueLazy{T}"/> from a <see cref="Func{T}"/>.</summary>
 940  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 941  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 942  public ValueLazy(Func<T> func)
 943  {
 944    if (func is null) throw new ArgumentNullException(nameof(func));
 945    _value = default;
 946    _func = func;
 947  }
 948
 949  /// <summary>Constructs a new <see cref="ValueLazy{T}"/> from a <see cref="Func{T}"/>.</summary>
 950  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 951  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 952  public static implicit operator ValueLazy<T>(Func<T> func) => new(func);
 953
 954  /// <summary>Constructs a new <see cref="ValueLazy{T}"/> from a <typeparamref name="T"/>.</summary>
 955  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 956  public static implicit operator ValueLazy<T>(T value) => new(value);
 957
 958  /// <summary>Checks for equality between <see cref="Value"/> and <paramref name="obj"/>.</summary>
 959  /// <param name="obj">The value to compare to <see cref="Value"/>.</param>
 960  /// <returns>True if <see cref="Value"/> and <paramref name="obj"/> are equal or False if not.</returns>
 961  public override bool Equals(object? obj)
 962  {
 963    if (obj is ValueLazy<T> slazy)
 964    {
 965      obj = slazy.Value;
 966    }
 967    return (Value, obj) switch
 968    {
 969      (null, null) => true,
 970      (_,    null) => false,
 971      (null,    _) => false,
 972      _ => Value!.Equals(obj),
 973    };
 974  }
 975
 976  /// <summary>Returns a string that represents <see cref="Value"/>.</summary>
 977  /// <returns>A string that represents <see cref="Value"/></returns>
 978  public override string? ToString() => Value?.ToString();
 979
 980  /// <summary>Gets the hash code of <see cref="Value"/>.</summary>
 981  /// <returns>The hash code of <see cref="Value"/>.</returns>
 982  public override int GetHashCode() => Value?.GetHashCode() ?? default;
 983
 984  /// <summary>Checks for equality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 985  /// <param name="left">The first value of the equality check.</param>
 986  /// <param name="right">The second value of the equality check.</param>
 987  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are equal or False if not.</returns>
 988  public static bool operator ==(ValueLazy<T> left, ValueLazy<T> right) => left.Equals(right);
 989
 990  /// <summary>Checks for inequality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 991  /// <param name="left">The first value of the inequality check.</param>
 992  /// <param name="right">The second value of the inequality check.</param>
 993  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are not equal or False if not.</returns>
 994  public static bool operator !=(ValueLazy<T> left, ValueLazy<T> right) => !(left == right);
 995}
 996
 997#endregion
 998
 999#region ValueLazyNoCatch<T>
 1000
 1001/// <summary>Provides support for lazy initialization.</summary>
 1002/// <typeparam name="T">The type of value that is being lazily initialized.</typeparam>
 1003public struct ValueLazyNoCatch<T> : ILazy<T>
 1004{
 1005  internal Func<T>? _func;
 1006  internal T? _value;
 1007
 1008  /// <inheritdoc />
 1009  public bool IsValueCreated => _func is null;
 1010
 1011  /// <inheritdoc />
 1012  public T Value => _func is null ? _value! : GetValueNoCatch();
 1013
 1014  /// <inheritdoc />
 1015  public LazyThreadSafetyMode ThreadSafety => LazyThreadSafetyMode.ExecutionAndPublication;
 1016
 1017  /// <inheritdoc />
 1018  public bool IsCachingExceptions => false;
 1019
 1020  /// <inheritdoc />
 1021  public bool IsStructCopySafe => false;
 1022
 1023  internal T GetValueNoCatch()
 1024  {
 1025    Func<T>? func = _func;
 1026    if (func is not null)
 1027    {
 1028      lock (func)
 1029      {
 1030        if (_func is not null)
 1031        {
 1032          _value = _func();
 1033          _func = null;
 1034        }
 1035      }
 1036    }
 1037    return _value!;
 1038  }
 1039
 1040  /// <summary>Constructs a new <see cref="ValueLazyNoCatch{T}"/> from a <typeparamref name="T"/>.</summary>
 1041  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 1042  public ValueLazyNoCatch(T value)
 1043  {
 1044    _func = null;
 1045    _value = value;
 1046  }
 1047
 1048  /// <summary>Constructs a new <see cref="ValueLazyNoCatch{T}"/> from a <see cref="Func{T}"/>.</summary>
 1049  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 1050  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 1051  public ValueLazyNoCatch(Func<T> func)
 1052  {
 1053    if (func is null) throw new ArgumentNullException(nameof(func));
 1054    _value = default;
 1055    _func = func;
 1056  }
 1057
 1058  /// <summary>Constructs a new <see cref="ValueLazyNoCatch{T}"/> from a <see cref="Func{T}"/>.</summary>
 1059  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 1060  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 1061  public static implicit operator ValueLazyNoCatch<T>(Func<T> func) => new(func);
 1062
 1063  /// <summary>Constructs a new <see cref="ValueLazyNoCatch{T}"/> from a <typeparamref name="T"/>.</summary>
 1064  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 1065  public static implicit operator ValueLazyNoCatch<T>(T value) => new(value);
 1066
 1067  /// <summary>Checks for equality between <see cref="Value"/> and <paramref name="obj"/>.</summary>
 1068  /// <param name="obj">The value to compare to <see cref="Value"/>.</param>
 1069  /// <returns>True if <see cref="Value"/> and <paramref name="obj"/> are equal or False if not.</returns>
 1070  public override bool Equals(object? obj)
 1071  {
 1072    if (obj is ValueLazyNoCatch<T> slazy)
 1073    {
 1074      obj = slazy.Value;
 1075    }
 1076    return (Value, obj) switch
 1077    {
 1078      (null, null) => true,
 1079      (_,    null) => false,
 1080      (null,    _) => false,
 1081      _ => Value!.Equals(obj),
 1082    };
 1083  }
 1084
 1085  /// <summary>Returns a string that represents <see cref="Value"/>.</summary>
 1086  /// <returns>A string that represents <see cref="Value"/></returns>
 1087  public override string? ToString() => Value?.ToString();
 1088
 1089  /// <summary>Gets the hash code of <see cref="Value"/>.</summary>
 1090  /// <returns>The hash code of <see cref="Value"/>.</returns>
 1091  public override int GetHashCode() => Value?.GetHashCode() ?? default;
 1092
 1093  /// <summary>Checks for equality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 1094  /// <param name="left">The first value of the equality check.</param>
 1095  /// <param name="right">The second value of the equality check.</param>
 1096  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are equal or False if not.</returns>
 1097  public static bool operator ==(ValueLazyNoCatch<T> left, ValueLazyNoCatch<T> right) => left.Equals(right);
 1098
 1099  /// <summary>Checks for inequality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 1100  /// <param name="left">The first value of the inequality check.</param>
 1101  /// <param name="right">The second value of the inequality check.</param>
 1102  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are not equal or False if not.</returns>
 1103  public static bool operator !=(ValueLazyNoCatch<T> left, ValueLazyNoCatch<T> right) => !(left == right);
 1104}
 1105
 1106#endregion
 1107
 1108#region ValueLazyNoLock<T>
 1109
 1110/// <summary>Provides support for lazy initialization.</summary>
 1111/// <typeparam name="T">The type of value that is being lazily initialized.</typeparam>
 1112public struct ValueLazyNoLock<T> : ILazy<T>
 1113{
 1114  internal Func<T>? _func;
 1115  internal T? _value;
 1116
 1117  /// <inheritdoc />
 1118  public bool IsValueCreated => _func is null;
 1119
 1120  /// <inheritdoc />
 1121  public T Value => _func is null ? _value! : GetValueNoLock();
 1122
 1123  /// <inheritdoc />
 1124  public LazyThreadSafetyMode ThreadSafety => LazyThreadSafetyMode.None;
 1125
 1126  /// <inheritdoc />
 1127  public bool IsCachingExceptions => true;
 1128
 1129  /// <inheritdoc />
 1130  public bool IsStructCopySafe => false;
 1131
 1132  internal T GetValueNoLock()
 1133  {
 1134    if (_func is not null)
 1135    {
 1136      try
 1137      {
 1138        _value = _func();
 1139        _func = null;
 1140      }
 1141      catch (Exception exception)
 1142      {
 1143        _func = () => throw exception;
 1144        throw;
 1145      }
 1146    }
 1147    return _value!;
 1148  }
 1149
 1150  /// <summary>Constructs a new <see cref="ValueLazyNoLock{T}"/> from a <typeparamref name="T"/>.</summary>
 1151  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 1152  public ValueLazyNoLock(T value)
 1153  {
 1154    _func = null;
 1155    _value = value;
 1156  }
 1157
 1158  /// <summary>Constructs a new <see cref="ValueLazyNoLock{T}"/> from a <see cref="Func{T}"/>.</summary>
 1159  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 1160  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 1161  public ValueLazyNoLock(Func<T> func)
 1162  {
 1163    if (func is null) throw new ArgumentNullException(nameof(func));
 1164    _value = default;
 1165    _func = func;
 1166  }
 1167
 1168  /// <summary>Constructs a new <see cref="ValueLazyNoLock{T}"/> from a <see cref="Func{T}"/>.</summary>
 1169  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 1170  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 1171  public static implicit operator ValueLazyNoLock<T>(Func<T> func) => new(func);
 1172
 1173  /// <summary>Constructs a new <see cref="ValueLazyNoLock{T}"/> from a <typeparamref name="T"/>.</summary>
 1174  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 1175  public static implicit operator ValueLazyNoLock<T>(T value) => new(value);
 1176
 1177  /// <summary>Checks for equality between <see cref="Value"/> and <paramref name="obj"/>.</summary>
 1178  /// <param name="obj">The value to compare to <see cref="Value"/>.</param>
 1179  /// <returns>True if <see cref="Value"/> and <paramref name="obj"/> are equal or False if not.</returns>
 1180  public override bool Equals(object? obj)
 1181  {
 1182    if (obj is ValueLazyNoLock<T> slazy)
 1183    {
 1184      obj = slazy.Value;
 1185    }
 1186    return (Value, obj) switch
 1187    {
 1188      (null, null) => true,
 1189      (_,    null) => false,
 1190      (null,    _) => false,
 1191      _ => Value!.Equals(obj),
 1192    };
 1193  }
 1194
 1195  /// <summary>Returns a string that represents <see cref="Value"/>.</summary>
 1196  /// <returns>A string that represents <see cref="Value"/></returns>
 1197  public override string? ToString() => Value?.ToString();
 1198
 1199  /// <summary>Gets the hash code of <see cref="Value"/>.</summary>
 1200  /// <returns>The hash code of <see cref="Value"/>.</returns>
 1201  public override int GetHashCode() => Value?.GetHashCode() ?? default;
 1202
 1203  /// <summary>Checks for equality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 1204  /// <param name="left">The first value of the equality check.</param>
 1205  /// <param name="right">The second value of the equality check.</param>
 1206  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are equal or False if not.</returns>
 1207  public static bool operator ==(ValueLazyNoLock<T> left, ValueLazyNoLock<T> right) => left.Equals(right);
 1208
 1209  /// <summary>Checks for inequality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 1210  /// <param name="left">The first value of the inequality check.</param>
 1211  /// <param name="right">The second value of the inequality check.</param>
 1212  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are not equal or False if not.</returns>
 1213  public static bool operator !=(ValueLazyNoLock<T> left, ValueLazyNoLock<T> right) => !(left == right);
 1214}
 1215
 1216#endregion
 1217
 1218#region ValueLazyNoLockNoCatch<T>
 1219
 1220/// <summary>Provides support for lazy initialization.</summary>
 1221/// <typeparam name="T">The type of value that is being lazily initialized.</typeparam>
 1222public struct ValueLazyNoLockNoCatch<T> : ILazy<T>
 1223{
 1224  internal Func<T>? _func;
 1225  internal T? _value;
 1226
 1227  /// <inheritdoc />
 1228  public bool IsValueCreated => _func is null;
 1229
 1230  /// <inheritdoc />
 1231  public T Value => _func is null ? _value! : GetValueNoLockNoCatch();
 1232
 1233  /// <inheritdoc />
 1234  public LazyThreadSafetyMode ThreadSafety => LazyThreadSafetyMode.None;
 1235
 1236  /// <inheritdoc />
 1237  public bool IsCachingExceptions => false;
 1238
 1239  /// <inheritdoc />
 1240  public bool IsStructCopySafe => false;
 1241
 1242  internal T GetValueNoLockNoCatch()
 1243  {
 1244    if (_func is not null)
 1245    {
 1246      _value = _func();
 1247      _func = null;
 1248    }
 1249    return _value!;
 1250  }
 1251
 1252  /// <summary>Constructs a new <see cref="ValueLazyNoLockNoCatch{T}"/> from a <typeparamref name="T"/>.</summary>
 1253  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 1254  public ValueLazyNoLockNoCatch(T value)
 1255  {
 1256    _func = null;
 1257    _value = value;
 1258  }
 1259
 1260  /// <summary>Constructs a new <see cref="ValueLazyNoLockNoCatch{T}"/> from a <see cref="Func{T}"/>.</summary>
 1261  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 1262  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 1263  public ValueLazyNoLockNoCatch(Func<T> func)
 1264  {
 1265    if (func is null) throw new ArgumentNullException(nameof(func));
 1266    _value = default;
 1267    _func = func;
 1268  }
 1269
 1270  /// <summary>Constructs a new <see cref="ValueLazyNoLockNoCatch{T}"/> from a <see cref="Func{T}"/>.</summary>
 1271  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 1272  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 1273  public static implicit operator ValueLazyNoLockNoCatch<T>(Func<T> func) => new(func);
 1274
 1275  /// <summary>Constructs a new <see cref="ValueLazyNoLockNoCatch{T}"/> from a <typeparamref name="T"/>.</summary>
 1276  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 1277  public static implicit operator ValueLazyNoLockNoCatch<T>(T value) => new(value);
 1278
 1279  /// <summary>Checks for equality between <see cref="Value"/> and <paramref name="obj"/>.</summary>
 1280  /// <param name="obj">The value to compare to <see cref="Value"/>.</param>
 1281  /// <returns>True if <see cref="Value"/> and <paramref name="obj"/> are equal or False if not.</returns>
 1282  public override bool Equals(object? obj)
 1283  {
 1284    if (obj is ValueLazyNoLockNoCatch<T> slazy)
 1285    {
 1286      obj = slazy.Value;
 1287    }
 1288    return (Value, obj) switch
 1289    {
 1290      (null, null) => true,
 1291      (_,    null) => false,
 1292      (null,    _) => false,
 1293      _ => Value!.Equals(obj),
 1294    };
 1295  }
 1296
 1297  /// <summary>Returns a string that represents <see cref="Value"/>.</summary>
 1298  /// <returns>A string that represents <see cref="Value"/></returns>
 1299  public override string? ToString() => Value?.ToString();
 1300
 1301  /// <summary>Gets the hash code of <see cref="Value"/>.</summary>
 1302  /// <returns>The hash code of <see cref="Value"/>.</returns>
 1303  public override int GetHashCode() => Value?.GetHashCode() ?? default;
 1304
 1305  /// <summary>Checks for equality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 1306  /// <param name="left">The first value of the equality check.</param>
 1307  /// <param name="right">The second value of the equality check.</param>
 1308  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are equal or False if not.</returns>
 1309  public static bool operator ==(ValueLazyNoLockNoCatch<T> left, ValueLazyNoLockNoCatch<T> right) => left.Equals(right);
 1310
 1311  /// <summary>Checks for inequality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 1312  /// <param name="left">The first value of the inequality check.</param>
 1313  /// <param name="right">The second value of the inequality check.</param>
 1314  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are not equal or False if not.</returns>
 1315  public static bool operator !=(ValueLazyNoLockNoCatch<T> left, ValueLazyNoLockNoCatch<T> right) => !(left == right);
 1316}
 1317
 1318#endregion
 1319
 1320#region ValueLazyPublicationLock<T>
 1321
 1322/// <summary>Provides support for lazy initialization.</summary>
 1323/// <typeparam name="T">The type of value that is being lazily initialized.</typeparam>
 1324public struct ValueLazyPublicationLock<T> : ILazy<T>
 1325{
 1326  internal Func<T>? _func;
 1327  internal T? _value;
 1328
 1329  /// <inheritdoc />
 1330  public bool IsValueCreated => _func is null;
 1331
 1332  /// <inheritdoc />
 1333  public T Value => _func is null ? _value! : GetValuePublicationLock();
 1334
 1335  /// <inheritdoc />
 1336  public LazyThreadSafetyMode ThreadSafety => LazyThreadSafetyMode.PublicationOnly;
 1337
 1338  /// <inheritdoc />
 1339  public bool IsCachingExceptions => true;
 1340
 1341  /// <inheritdoc />
 1342  public bool IsStructCopySafe => false;
 1343
 1344  internal T GetValuePublicationLock()
 1345  {
 1346    Func<T>? func = _func;
 1347    if (func is not null)
 1348    {
 1349      try
 1350      {
 1351        T value = func();
 1352        lock (func)
 1353        {
 1354          if (_func is not null)
 1355          {
 1356            if (ReferenceEquals(_func, func))
 1357            {
 1358              _value = value;
 1359              _func = null;
 1360            }
 1361            else
 1362            {
 1363              _ = _func();
 1364            }
 1365          }
 1366        }
 1367      }
 1368      catch (Exception exception)
 1369      {
 1370        lock (func)
 1371        {
 1372          if (_func is not null)
 1373          {
 1374            if (ReferenceEquals(_func, func))
 1375            {
 1376              _func = () => throw exception;
 1377              throw;
 1378            }
 1379            else
 1380            {
 1381              _ = _func();
 1382            }
 1383          }
 1384        }
 1385      }
 1386    }
 1387    return _value!;
 1388  }
 1389
 1390  /// <summary>Constructs a new <see cref="ValueLazyPublicationLock{T}"/> from a <typeparamref name="T"/>.</summary>
 1391  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 1392  public ValueLazyPublicationLock(T value)
 1393  {
 1394    _func = null;
 1395    _value = value;
 1396  }
 1397
 1398  /// <summary>Constructs a new <see cref="ValueLazyPublicationLock{T}"/> from a <see cref="Func{T}"/>.</summary>
 1399  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 1400  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 1401  public ValueLazyPublicationLock(Func<T> func)
 1402  {
 1403    if (func is null) throw new ArgumentNullException(nameof(func));
 1404    _value = default;
 1405    _func = func;
 1406  }
 1407
 1408  /// <summary>Constructs a new <see cref="ValueLazyPublicationLock{T}"/> from a <see cref="Func{T}"/>.</summary>
 1409  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 1410  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 1411  public static implicit operator ValueLazyPublicationLock<T>(Func<T> func) => new(func);
 1412
 1413  /// <summary>Constructs a new <see cref="ValueLazyPublicationLock{T}"/> from a <typeparamref name="T"/>.</summary>
 1414  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 1415  public static implicit operator ValueLazyPublicationLock<T>(T value) => new(value);
 1416
 1417  /// <summary>Checks for equality between <see cref="Value"/> and <paramref name="obj"/>.</summary>
 1418  /// <param name="obj">The value to compare to <see cref="Value"/>.</param>
 1419  /// <returns>True if <see cref="Value"/> and <paramref name="obj"/> are equal or False if not.</returns>
 1420  public override bool Equals(object? obj)
 1421  {
 1422    if (obj is ValueLazyPublicationLock<T> slazy)
 1423    {
 1424      obj = slazy.Value;
 1425    }
 1426    return (Value, obj) switch
 1427    {
 1428      (null, null) => true,
 1429      (_,    null) => false,
 1430      (null,    _) => false,
 1431      _ => Value!.Equals(obj),
 1432    };
 1433  }
 1434
 1435  /// <summary>Returns a string that represents <see cref="Value"/>.</summary>
 1436  /// <returns>A string that represents <see cref="Value"/></returns>
 1437  public override string? ToString() => Value?.ToString();
 1438
 1439  /// <summary>Gets the hash code of <see cref="Value"/>.</summary>
 1440  /// <returns>The hash code of <see cref="Value"/>.</returns>
 1441  public override int GetHashCode() => Value?.GetHashCode() ?? default;
 1442
 1443  /// <summary>Checks for equality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 1444  /// <param name="left">The first value of the equality check.</param>
 1445  /// <param name="right">The second value of the equality check.</param>
 1446  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are equal or False if not.</returns>
 1447  public static bool operator ==(ValueLazyPublicationLock<T> left, ValueLazyPublicationLock<T> right) => left.Equals(rig
 1448
 1449  /// <summary>Checks for inequality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 1450  /// <param name="left">The first value of the inequality check.</param>
 1451  /// <param name="right">The second value of the inequality check.</param>
 1452  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are not equal or False if not.</returns>
 1453  public static bool operator !=(ValueLazyPublicationLock<T> left, ValueLazyPublicationLock<T> right) => !(left == right
 1454}
 1455
 1456#endregion
 1457
 1458#region ValueLazyPublicationLockNoCatch<T>
 1459
 1460/// <summary>Provides support for lazy initialization.</summary>
 1461/// <typeparam name="T">The type of value that is being lazily initialized.</typeparam>
 1462public struct ValueLazyPublicationLockNoCatch<T> : ILazy<T>
 1463{
 1464  internal Func<T>? _func;
 1465  internal T? _value;
 1466
 1467  /// <inheritdoc />
 1468  public bool IsValueCreated => _func is null;
 1469
 1470  /// <inheritdoc />
 1471  public T Value => _func is null ? _value! : GetValuePublicationLockNoCatch();
 1472
 1473  /// <inheritdoc />
 1474  public LazyThreadSafetyMode ThreadSafety => LazyThreadSafetyMode.PublicationOnly;
 1475
 1476  /// <inheritdoc />
 1477  public bool IsCachingExceptions => false;
 1478
 1479  /// <inheritdoc />
 1480  public bool IsStructCopySafe => false;
 1481
 1482  internal T GetValuePublicationLockNoCatch()
 1483  {
 1484
 1485    Func<T>? func = _func;
 1486    if (func is not null)
 1487    {
 1488      T value = func();
 1489      lock (func)
 1490      {
 1491        if (_func is not null)
 1492        {
 1493          _value = value;
 1494          _func = null;
 1495        }
 1496      }
 1497    }
 1498    return _value!;
 1499  }
 1500
 1501  /// <summary>Constructs a new <see cref="ValueLazyPublicationLockNoCatch{T}"/> from a <typeparamref name="T"/>.</summa
 1502  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 1503  public ValueLazyPublicationLockNoCatch(T value)
 1504  {
 1505    _func = null;
 1506    _value = value;
 1507  }
 1508
 1509  /// <summary>Constructs a new <see cref="ValueLazyPublicationLockNoCatch{T}"/> from a <see cref="Func{T}"/>.</summary>
 1510  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 1511  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 1512  public ValueLazyPublicationLockNoCatch(Func<T> func)
 1513  {
 1514    if (func is null) throw new ArgumentNullException(nameof(func));
 1515    _value = default;
 1516    _func = func;
 1517  }
 1518
 1519  /// <summary>Constructs a new <see cref="ValueLazyPublicationLockNoCatch{T}"/> from a <see cref="Func{T}"/>.</summary>
 1520  /// <param name="func">The method used to initialize <see cref="Value"/>.</param>
 1521  /// <exception cref="ArgumentNullException">Thrown when <paramref name="func"/> is null.</exception>
 1522  public static implicit operator ValueLazyPublicationLockNoCatch<T>(Func<T> func) => new(func);
 1523
 1524  /// <summary>Constructs a new <see cref="ValueLazyPublicationLockNoCatch{T}"/> from a <typeparamref name="T"/>.</summa
 1525  /// <param name="value">The value to initialize <see cref="Value"/> with.</param>
 1526  public static implicit operator ValueLazyPublicationLockNoCatch<T>(T value) => new(value);
 1527
 1528  /// <summary>Checks for equality between <see cref="Value"/> and <paramref name="obj"/>.</summary>
 1529  /// <param name="obj">The value to compare to <see cref="Value"/>.</param>
 1530  /// <returns>True if <see cref="Value"/> and <paramref name="obj"/> are equal or False if not.</returns>
 1531  public override bool Equals(object? obj)
 1532  {
 1533    if (obj is ValueLazyPublicationLockNoCatch<T> slazy)
 1534    {
 1535      obj = slazy.Value;
 1536    }
 1537    return (Value, obj) switch
 1538    {
 1539      (null, null) => true,
 1540      (_,    null) => false,
 1541      (null,    _) => false,
 1542      _ => Value!.Equals(obj),
 1543    };
 1544  }
 1545
 1546  /// <summary>Returns a string that represents <see cref="Value"/>.</summary>
 1547  /// <returns>A string that represents <see cref="Value"/></returns>
 1548  public override string? ToString() => Value?.ToString();
 1549
 1550  /// <summary>Gets the hash code of <see cref="Value"/>.</summary>
 1551  /// <returns>The hash code of <see cref="Value"/>.</returns>
 1552  public override int GetHashCode() => Value?.GetHashCode() ?? default;
 1553
 1554  /// <summary>Checks for equality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 1555  /// <param name="left">The first value of the equality check.</param>
 1556  /// <param name="right">The second value of the equality check.</param>
 1557  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are equal or False if not.</returns>
 1558  public static bool operator ==(ValueLazyPublicationLockNoCatch<T> left, ValueLazyPublicationLockNoCatch<T> right) => l
 1559
 1560  /// <summary>Checks for inequality between <paramref name="left"/> and <paramref name="right"/>.</summary>
 1561  /// <param name="left">The first value of the inequality check.</param>
 1562  /// <param name="right">The second value of the inequality check.</param>
 1563  /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are not equal or False if not.</returns>
 1564  public static bool operator !=(ValueLazyPublicationLockNoCatch<T> left, ValueLazyPublicationLockNoCatch<T> right) => !
 1565}
 1566
 1567  #endregion