private static AsyncLock GetExclusiveLock <T>(this T obj)
            where T : class
        {
            AsyncLock @lock;

            switch (obj)
            {
            case null:
                throw new ArgumentNullException(nameof(obj));

            case AsyncExclusiveLock exclusive:
                @lock = AsyncLock.Exclusive(exclusive);
                break;

            case SemaphoreSlim semaphore:
                @lock = AsyncLock.Semaphore(semaphore);
                break;

            case AsyncReaderWriterLock rwl:
                @lock = AsyncLock.WriteLock(rwl);
                break;

            case ReaderWriterLockSlim _:
            case WaitHandle _:
            case ReaderWriterLock _:
                throw new ArgumentException(ExceptionMessages.UnsupportedLockAcquisition, nameof(obj));

            default:
                @lock = AsyncLock.Exclusive(obj.GetUserData()
                                            .GetOrSet(ExclusiveLock, () => new AsyncExclusiveLock()));
                break;
            }

            return(@lock);
        }
        public static async Task SemaphoreLock()
        {
            using var sem   = new SemaphoreSlim(3);
            using var @lock = AsyncLock.Semaphore(sem);
            var holder = await @lock.TryAcquireAsync(DefaultTimeout, CancellationToken.None);

            if (holder)
            {
            }
            else
            {
                throw new Exception();
            }
            Equal(2, sem.CurrentCount);
            holder.Dispose();
            Equal(3, sem.CurrentCount);
        }
        private static AsyncLock GetExclusiveLock <T>(this T obj)
            where T : class
        {
            AsyncLock @lock;

            switch (obj)
            {
            case null:
                throw new ArgumentNullException(nameof(obj));

            case AsyncSharedLock shared:
                @lock = AsyncLock.Exclusive(shared);
                break;

            case AsyncExclusiveLock exclusive:
                @lock = AsyncLock.Exclusive(exclusive);
                break;

            case SemaphoreSlim semaphore:
                @lock = AsyncLock.Semaphore(semaphore);
                break;

            case AsyncReaderWriterLock rwl:
                @lock = AsyncLock.WriteLock(rwl);
                break;

            case ReaderWriterLockSlim _:
            case WaitHandle _:
            case ReaderWriterLock _:
            case string str when !(string.IsInterned(str) is null):
                throw new InvalidOperationException(ExceptionMessages.UnsupportedLockAcquisition);

            default:
                @lock = AsyncLock.Exclusive(obj.GetUserData().GetOrSet(ExclusiveLock));
                break;
            }

            return(@lock);
        }