Browse Source

More efficient array creation (#11468)

Bond-009 1 year ago
parent
commit
3feb3f81bf
25 changed files with 55 additions and 131 deletions
  1. 2 6
      Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs
  2. 2 12
      Emby.Server.Implementations/Data/SqliteItemRepository.cs
  3. 1 1
      Emby.Server.Implementations/Library/IgnorePatterns.cs
  4. 2 7
      Emby.Server.Implementations/Library/LibraryManager.cs
  5. 2 2
      Emby.Server.Implementations/Library/UserViewManager.cs
  6. 3 8
      Emby.Server.Implementations/Playlists/PlaylistManager.cs
  7. 3 4
      Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
  8. 4 7
      Emby.Server.Implementations/Session/SessionManager.cs
  9. 3 9
      Jellyfin.Api/Controllers/ItemUpdateController.cs
  10. 2 2
      Jellyfin.Api/Controllers/LibraryController.cs
  11. 1 1
      Jellyfin.Api/Controllers/LibraryStructureController.cs
  12. 2 7
      Jellyfin.Api/Controllers/UserViewsController.cs
  13. 2 10
      Jellyfin.Api/Extensions/DtoExtensions.cs
  14. 4 14
      MediaBrowser.Controller/Entities/BaseItem.cs
  15. 2 6
      MediaBrowser.Controller/Entities/Extensions.cs
  16. 2 2
      MediaBrowser.Controller/Entities/TagExtensions.cs
  17. 2 2
      MediaBrowser.Controller/Library/ItemResolveArgs.cs
  18. 1 1
      MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs
  19. 1 3
      MediaBrowser.Controller/Session/SessionInfo.cs
  20. 1 3
      MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs
  21. 1 1
      src/Jellyfin.LiveTv/Channels/ChannelManager.cs
  22. 6 8
      src/Jellyfin.LiveTv/Listings/ListingsManager.cs
  23. 1 1
      src/Jellyfin.LiveTv/LiveTvManager.cs
  24. 2 10
      src/Jellyfin.LiveTv/Timers/ItemDataProvider.cs
  25. 3 4
      src/Jellyfin.LiveTv/TunerHosts/TunerHostManager.cs

+ 2 - 6
Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs

@@ -127,15 +127,11 @@ namespace Emby.Server.Implementations.AppBase
 
             if (_configurationFactories is null)
             {
-                _configurationFactories = new[] { factory };
+                _configurationFactories = [factory];
             }
             else
             {
-                var oldLen = _configurationFactories.Length;
-                var arr = new IConfigurationFactory[oldLen + 1];
-                _configurationFactories.CopyTo(arr, 0);
-                arr[oldLen] = factory;
-                _configurationFactories = arr;
+                _configurationFactories = [.._configurationFactories, factory];
             }
 
             _configurationStores = _configurationFactories

+ 2 - 12
Emby.Server.Implementations/Data/SqliteItemRepository.cs

@@ -2323,14 +2323,7 @@ namespace Emby.Server.Implementations.Data
 
                 columns.Add(builder.ToString());
 
-                var oldLen = query.ExcludeItemIds.Length;
-                var newLen = oldLen + item.ExtraIds.Length + 1;
-                var excludeIds = new Guid[newLen];
-                query.ExcludeItemIds.CopyTo(excludeIds, 0);
-                excludeIds[oldLen] = item.Id;
-                item.ExtraIds.CopyTo(excludeIds, oldLen + 1);
-
-                query.ExcludeItemIds = excludeIds;
+                query.ExcludeItemIds = [..query.ExcludeItemIds, item.Id, ..item.ExtraIds];
                 query.ExcludeProviderIds = item.ProviderIds;
             }
 
@@ -2838,10 +2831,7 @@ namespace Emby.Server.Implementations.Data
                     prepend.Add((ItemSortBy.Random, SortOrder.Ascending));
                 }
 
-                var arr = new (ItemSortBy, SortOrder)[prepend.Count + orderBy.Count];
-                prepend.CopyTo(arr, 0);
-                orderBy.CopyTo(arr, prepend.Count);
-                orderBy = query.OrderBy = arr;
+                orderBy = query.OrderBy = [..prepend, ..orderBy];
             }
             else if (orderBy.Count == 0)
             {

+ 1 - 1
Emby.Server.Implementations/Library/IgnorePatterns.cs

@@ -103,7 +103,7 @@ namespace Emby.Server.Implementations.Library
             }
         };
 
-        private static readonly Glob[] _globs = _patterns.Select(p => Glob.Parse(p, _globOptions)).ToArray();
+        private static readonly Glob[] _globs = Array.ConvertAll(_patterns, p => Glob.Parse(p, _globOptions));
 
         /// <summary>
         /// Returns true if the supplied path should be ignored.

+ 2 - 7
Emby.Server.Implementations/Library/LibraryManager.cs

@@ -3038,9 +3038,7 @@ namespace Emby.Server.Implementations.Library
             {
                 var libraryOptions = CollectionFolder.GetLibraryOptions(virtualFolderPath);
 
-                var list = libraryOptions.PathInfos.ToList();
-                list.Add(pathInfo);
-                libraryOptions.PathInfos = list.ToArray();
+                libraryOptions.PathInfos = [..libraryOptions.PathInfos, pathInfo];
 
                 SyncLibraryOptionsToLocations(virtualFolderPath, libraryOptions);
 
@@ -3059,8 +3057,7 @@ namespace Emby.Server.Implementations.Library
 
             SyncLibraryOptionsToLocations(virtualFolderPath, libraryOptions);
 
-            var list = libraryOptions.PathInfos.ToList();
-            foreach (var originalPathInfo in list)
+            foreach (var originalPathInfo in libraryOptions.PathInfos)
             {
                 if (string.Equals(mediaPath.Path, originalPathInfo.Path, StringComparison.Ordinal))
                 {
@@ -3069,8 +3066,6 @@ namespace Emby.Server.Implementations.Library
                 }
             }
 
-            libraryOptions.PathInfos = list.ToArray();
-
             CollectionFolder.SaveLibraryOptions(virtualFolderPath, libraryOptions);
         }
 

+ 2 - 2
Emby.Server.Implementations/Library/UserViewManager.cs

@@ -303,8 +303,8 @@ namespace Emby.Server.Implementations.Library
             {
                 // Handle situations with the grouping setting, e.g. movies showing up in tv, etc.
                 // Thanks to mixed content libraries included in the UserView
-                var hasCollectionType = parents.OfType<UserView>().ToArray();
-                if (hasCollectionType.Length > 0)
+                var hasCollectionType = parents.OfType<UserView>().ToList();
+                if (hasCollectionType.Count > 0)
                 {
                     if (hasCollectionType.All(i => i.CollectionType == CollectionType.movies))
                     {

+ 3 - 8
Emby.Server.Implementations/Playlists/PlaylistManager.cs

@@ -226,13 +226,8 @@ namespace Emby.Server.Implementations.Playlists
                 return;
             }
 
-            // Create a new array with the updated playlist items
-            var newLinkedChildren = new LinkedChild[playlist.LinkedChildren.Length + childrenToAdd.Count];
-            playlist.LinkedChildren.CopyTo(newLinkedChildren, 0);
-            childrenToAdd.CopyTo(newLinkedChildren, playlist.LinkedChildren.Length);
-
             // Update the playlist in the repository
-            playlist.LinkedChildren = newLinkedChildren;
+            playlist.LinkedChildren = [..playlist.LinkedChildren, ..childrenToAdd];
 
             await UpdatePlaylistInternal(playlist).ConfigureAwait(false);
 
@@ -526,8 +521,8 @@ namespace Emby.Server.Implementations.Playlists
             foreach (var playlist in playlists)
             {
                 // Update owner if shared
-                var rankedShares = playlist.Shares.OrderByDescending(x => x.CanEdit).ToArray();
-                if (rankedShares.Length > 0)
+                var rankedShares = playlist.Shares.OrderByDescending(x => x.CanEdit).ToList();
+                if (rankedShares.Count > 0)
                 {
                     playlist.OwnerUserId = rankedShares[0].UserId;
                     playlist.Shares = rankedShares.Skip(1).ToArray();

+ 3 - 4
Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs

@@ -256,8 +256,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
         {
             get
             {
-                var triggers = InternalTriggers;
-                return triggers.Select(i => i.Item1).ToArray();
+                return Array.ConvertAll(InternalTriggers, i => i.Item1);
             }
 
             set
@@ -269,7 +268,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
 
                 SaveTriggers(triggerList);
 
-                InternalTriggers = triggerList.Select(i => new Tuple<TaskTriggerInfo, ITaskTrigger>(i, GetTrigger(i))).ToArray();
+                InternalTriggers = Array.ConvertAll(triggerList, i => new Tuple<TaskTriggerInfo, ITaskTrigger>(i, GetTrigger(i)));
             }
         }
 
@@ -503,7 +502,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
         private Tuple<TaskTriggerInfo, ITaskTrigger>[] LoadTriggers()
         {
             // This null check is not great, but is needed to handle bad user input, or user mucking with the config file incorrectly
-            var settings = LoadTriggerSettings().Where(i => i is not null).ToArray();
+            var settings = LoadTriggerSettings().Where(i => i is not null);
 
             return settings.Select(i => new Tuple<TaskTriggerInfo, ITaskTrigger>(i, GetTrigger(i))).ToArray();
         }

+ 4 - 7
Emby.Server.Implementations/Session/SessionManager.cs

@@ -400,7 +400,7 @@ namespace Emby.Server.Implementations.Session
             {
                 session.NowPlayingQueue = nowPlayingQueue;
 
-                var itemIds = nowPlayingQueue.Select(queue => queue.Id).ToArray();
+                var itemIds = Array.ConvertAll(nowPlayingQueue, queue => queue.Id);
                 session.NowPlayingQueueFullItems = _dtoService.GetBaseItemDtos(
                     _libraryManager.GetItemList(new InternalItemsQuery { ItemIds = itemIds }),
                     new DtoOptions(true));
@@ -1386,16 +1386,13 @@ namespace Emby.Server.Implementations.Session
             if (session.AdditionalUsers.All(i => !i.UserId.Equals(userId)))
             {
                 var user = _userManager.GetUserById(userId);
-
-                var list = session.AdditionalUsers.ToList();
-
-                list.Add(new SessionUserInfo
+                var newUser = new SessionUserInfo
                 {
                     UserId = userId,
                     UserName = user.Username
-                });
+                };
 
-                session.AdditionalUsers = list.ToArray();
+                session.AdditionalUsers = [..session.AdditionalUsers, newUser];
             }
         }
 

+ 3 - 9
Jellyfin.Api/Controllers/ItemUpdateController.cs

@@ -264,7 +264,7 @@ public class ItemUpdateController : BaseJellyfinApiController
 
         if (request.Studios is not null)
         {
-            item.Studios = request.Studios.Select(x => x.Name).ToArray();
+            item.Studios = Array.ConvertAll(request.Studios, x => x.Name);
         }
 
         if (request.DateCreated.HasValue)
@@ -379,10 +379,7 @@ public class ItemUpdateController : BaseJellyfinApiController
         {
             if (item is IHasAlbumArtist hasAlbumArtists)
             {
-                hasAlbumArtists.AlbumArtists = request
-                    .AlbumArtists
-                    .Select(i => i.Name)
-                    .ToArray();
+                hasAlbumArtists.AlbumArtists = Array.ConvertAll(request.AlbumArtists, i => i.Name);
             }
         }
 
@@ -390,10 +387,7 @@ public class ItemUpdateController : BaseJellyfinApiController
         {
             if (item is IHasArtist hasArtists)
             {
-                hasArtists.Artists = request
-                    .ArtistItems
-                    .Select(i => i.Name)
-                    .ToArray();
+                hasArtists.Artists = Array.ConvertAll(request.ArtistItems, i => i.Name);
             }
         }
 

+ 2 - 2
Jellyfin.Api/Controllers/LibraryController.cs

@@ -158,13 +158,13 @@ public class LibraryController : BaseJellyfinApiController
             return NotFound();
         }
 
-        IEnumerable<BaseItem> themeItems;
+        IReadOnlyList<BaseItem> themeItems;
 
         while (true)
         {
             themeItems = item.GetThemeSongs();
 
-            if (themeItems.Any() || !inheritFromParent)
+            if (themeItems.Count > 0 || !inheritFromParent)
             {
                 break;
             }

+ 1 - 1
Jellyfin.Api/Controllers/LibraryStructureController.cs

@@ -85,7 +85,7 @@ public class LibraryStructureController : BaseJellyfinApiController
 
         if (paths is not null && paths.Length > 0)
         {
-            libraryOptions.PathInfos = paths.Select(i => new MediaPathInfo(i)).ToArray();
+            libraryOptions.PathInfos = Array.ConvertAll(paths, i => new MediaPathInfo(i));
         }
 
         await _libraryManager.AddVirtualFolder(name, collectionType, libraryOptions, refreshLibrary).ConfigureAwait(false);

+ 2 - 7
Jellyfin.Api/Controllers/UserViewsController.cs

@@ -85,16 +85,11 @@ public class UserViewsController : BaseJellyfinApiController
         var folders = _userViewManager.GetUserViews(query);
 
         var dtoOptions = new DtoOptions().AddClientFields(User);
-        var fields = dtoOptions.Fields.ToList();
-
-        fields.Add(ItemFields.PrimaryImageAspectRatio);
-        fields.Add(ItemFields.DisplayPreferencesId);
-        dtoOptions.Fields = fields.ToArray();
+        dtoOptions.Fields = [..dtoOptions.Fields, ItemFields.PrimaryImageAspectRatio, ItemFields.DisplayPreferencesId];
 
         var user = _userManager.GetUserById(userId.Value);
 
-        var dtos = folders.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user))
-            .ToArray();
+        var dtos = Array.ConvertAll(folders, i => _dtoService.GetBaseItemDto(i, dtoOptions, user));
 
         return new QueryResult<BaseItemDto>(dtos);
     }

+ 2 - 10
Jellyfin.Api/Extensions/DtoExtensions.cs

@@ -43,11 +43,7 @@ public static class DtoExtensions
                 client.Contains("media center", StringComparison.OrdinalIgnoreCase) ||
                 client.Contains("classic", StringComparison.OrdinalIgnoreCase))
             {
-                int oldLen = dtoOptions.Fields.Count;
-                var arr = new ItemFields[oldLen + 1];
-                dtoOptions.Fields.CopyTo(arr, 0);
-                arr[oldLen] = ItemFields.RecursiveItemCount;
-                dtoOptions.Fields = arr;
+                dtoOptions.Fields = [..dtoOptions.Fields, ItemFields.RecursiveItemCount];
             }
         }
 
@@ -61,11 +57,7 @@ public static class DtoExtensions
                 client.Contains("samsung", StringComparison.OrdinalIgnoreCase) ||
                 client.Contains("androidtv", StringComparison.OrdinalIgnoreCase))
             {
-                int oldLen = dtoOptions.Fields.Count;
-                var arr = new ItemFields[oldLen + 1];
-                dtoOptions.Fields.CopyTo(arr, 0);
-                arr[oldLen] = ItemFields.ChildCount;
-                dtoOptions.Fields = arr;
+                dtoOptions.Fields = [..dtoOptions.Fields, ItemFields.ChildCount];
             }
         }
 

+ 4 - 14
MediaBrowser.Controller/Entities/BaseItem.cs

@@ -1779,14 +1779,11 @@ namespace MediaBrowser.Controller.Entities
                 int curLen = current.Length;
                 if (curLen == 0)
                 {
-                    Studios = new[] { name };
+                    Studios = [name];
                 }
                 else
                 {
-                    var newArr = new string[curLen + 1];
-                    current.CopyTo(newArr, 0);
-                    newArr[curLen] = name;
-                    Studios = newArr;
+                    Studios = [..current, name];
                 }
             }
         }
@@ -1808,9 +1805,7 @@ namespace MediaBrowser.Controller.Entities
             var genres = Genres;
             if (!genres.Contains(name, StringComparison.OrdinalIgnoreCase))
             {
-                var list = genres.ToList();
-                list.Add(name);
-                Genres = list.ToArray();
+                Genres = [..genres, name];
             }
         }
 
@@ -1980,12 +1975,7 @@ namespace MediaBrowser.Controller.Entities
 
         public void AddImage(ItemImageInfo image)
         {
-            var current = ImageInfos;
-            var currentCount = current.Length;
-            var newArr = new ItemImageInfo[currentCount + 1];
-            current.CopyTo(newArr, 0);
-            newArr[currentCount] = image;
-            ImageInfos = newArr;
+            ImageInfos = [..ImageInfos, image];
         }
 
         public virtual Task UpdateToRepositoryAsync(ItemUpdateType updateReason, CancellationToken cancellationToken)

+ 2 - 6
MediaBrowser.Controller/Entities/Extensions.cs

@@ -30,15 +30,11 @@ namespace MediaBrowser.Controller.Entities
 
                 if (item.RemoteTrailers.Count == 0)
                 {
-                    item.RemoteTrailers = new[] { mediaUrl };
+                    item.RemoteTrailers = [mediaUrl];
                 }
                 else
                 {
-                    var oldIds = item.RemoteTrailers;
-                    var newIds = new MediaUrl[oldIds.Count + 1];
-                    oldIds.CopyTo(newIds);
-                    newIds[oldIds.Count] = mediaUrl;
-                    item.RemoteTrailers = newIds;
+                    item.RemoteTrailers = [..item.RemoteTrailers, mediaUrl];
                 }
             }
         }

+ 2 - 2
MediaBrowser.Controller/Entities/TagExtensions.cs

@@ -21,11 +21,11 @@ namespace MediaBrowser.Controller.Entities
             {
                 if (current.Length == 0)
                 {
-                    item.Tags = new[] { name };
+                    item.Tags = [name];
                 }
                 else
                 {
-                    item.Tags = current.Concat(new[] { name }).ToArray();
+                    item.Tags = [..current, name];
                 }
             }
         }

+ 2 - 2
MediaBrowser.Controller/Library/ItemResolveArgs.cs

@@ -116,8 +116,8 @@ namespace MediaBrowser.Controller.Library
         {
             get
             {
-                var paths = string.IsNullOrEmpty(Path) ? Array.Empty<string>() : new[] { Path };
-                return AdditionalLocations is null ? paths : paths.Concat(AdditionalLocations).ToArray();
+                var paths = string.IsNullOrEmpty(Path) ? Array.Empty<string>() : [Path];
+                return AdditionalLocations is null ? paths : [..paths, ..AdditionalLocations];
             }
         }
 

+ 1 - 1
MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs

@@ -288,7 +288,7 @@ namespace MediaBrowser.Controller.Net
 
             lock (_activeConnectionsLock)
             {
-                foreach (var connection in _activeConnections.ToArray())
+                foreach (var connection in _activeConnections.ToList())
                 {
                     DisposeConnection(connection);
                 }

+ 1 - 3
MediaBrowser.Controller/Session/SessionInfo.cs

@@ -270,9 +270,7 @@ namespace MediaBrowser.Controller.Session
 
         public void AddController(ISessionController controller)
         {
-            var controllers = SessionControllers.ToList();
-            controllers.Add(controller);
-            SessionControllers = controllers.ToArray();
+            SessionControllers = [..SessionControllers, controller];
         }
 
         public bool ContainsUser(Guid userId)

+ 1 - 3
MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs

@@ -117,9 +117,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers
                     var artist = reader.ReadNormalizedString();
                     if (!string.IsNullOrEmpty(artist) && item is MusicVideo artistVideo)
                     {
-                        var list = artistVideo.Artists.ToList();
-                        list.Add(artist);
-                        artistVideo.Artists = list.ToArray();
+                        artistVideo.Artists = [..artistVideo.Artists, artist];
                     }
 
                     break;

+ 1 - 1
src/Jellyfin.LiveTv/Channels/ChannelManager.cs

@@ -1130,7 +1130,7 @@ namespace Jellyfin.LiveTv.Channels
             {
                 if (!item.Tags.Contains("livestream", StringComparison.OrdinalIgnoreCase))
                 {
-                    item.Tags = item.Tags.Concat(new[] { "livestream" }).ToArray();
+                    item.Tags = [..item.Tags, "livestream"];
                     _logger.LogDebug("Forcing update due to Tags {0}", item.Name);
                     forceUpdate = true;
                 }

+ 6 - 8
src/Jellyfin.LiveTv/Listings/ListingsManager.cs

@@ -60,14 +60,13 @@ public class ListingsManager : IListingsManager
 
         var config = _config.GetLiveTvConfiguration();
 
-        var list = config.ListingProviders.ToList();
-        int index = list.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase));
+        var list = config.ListingProviders;
+        int index = Array.FindIndex(list, i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase));
 
         if (index == -1 || string.IsNullOrWhiteSpace(info.Id))
         {
             info.Id = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);
-            list.Add(info);
-            config.ListingProviders = list.ToArray();
+            config.ListingProviders = [..list, info];
         }
         else
         {
@@ -236,13 +235,12 @@ public class ListingsManager : IListingsManager
 
         if (!string.Equals(tunerChannelNumber, providerChannelNumber, StringComparison.OrdinalIgnoreCase))
         {
-            var list = listingsProviderInfo.ChannelMappings.ToList();
-            list.Add(new NameValuePair
+            var newItem = new NameValuePair
             {
                 Name = tunerChannelNumber,
                 Value = providerChannelNumber
-            });
-            listingsProviderInfo.ChannelMappings = list.ToArray();
+            };
+            listingsProviderInfo.ChannelMappings = [..listingsProviderInfo.ChannelMappings, newItem];
         }
 
         _config.SaveConfiguration("livetv", config);

+ 1 - 1
src/Jellyfin.LiveTv/LiveTvManager.cs

@@ -939,7 +939,7 @@ namespace Jellyfin.LiveTv
                     {
                         var internalChannelId = _tvDtoService.GetInternalChannelId(i.Item2.Name, i.Item1.ChannelId);
                         var channel = _libraryManager.GetItemById(internalChannelId);
-                        channelName = channel is null ? null : channel.Name;
+                        channelName = channel?.Name;
                     }
 
                     return _tvDtoService.GetSeriesTimerInfoDto(i.Item1, i.Item2, channelName);

+ 2 - 10
src/Jellyfin.LiveTv/Timers/ItemDataProvider.cs

@@ -115,11 +115,7 @@ namespace Jellyfin.LiveTv.Timers
                     throw new ArgumentException("item already exists", nameof(item));
                 }
 
-                int oldLen = _items.Length;
-                var newList = new T[oldLen + 1];
-                _items.CopyTo(newList, 0);
-                newList[oldLen] = item;
-                _items = newList;
+                _items = [.._items, item];
 
                 SaveList();
             }
@@ -134,11 +130,7 @@ namespace Jellyfin.LiveTv.Timers
                 int index = Array.FindIndex(_items, i => EqualityComparer(i, item));
                 if (index == -1)
                 {
-                    int oldLen = _items.Length;
-                    var newList = new T[oldLen + 1];
-                    _items.CopyTo(newList, 0);
-                    newList[oldLen] = item;
-                    _items = newList;
+                    _items = [.._items, item];
                 }
                 else
                 {

+ 3 - 4
src/Jellyfin.LiveTv/TunerHosts/TunerHostManager.cs

@@ -76,14 +76,13 @@ public class TunerHostManager : ITunerHostManager
 
         var config = _config.GetLiveTvConfiguration();
 
-        var list = config.TunerHosts.ToList();
-        var index = list.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase));
+        var list = config.TunerHosts;
+        var index = Array.FindIndex(list, i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase));
 
         if (index == -1 || string.IsNullOrWhiteSpace(info.Id))
         {
             info.Id = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);
-            list.Add(info);
-            config.TunerHosts = list.ToArray();
+            config.TunerHosts = [..list, info];
         }
         else
         {