{"record":{"id":"25f7cc468e8c5997","repo":"dotnet/wpf","slug":"sr-strokeisduplicated","errorCode":null,"errorMessage":"SR.StrokeIsDuplicated","messagePattern":"SR\\.StrokeIsDuplicated","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Ink/StrokeCollection.cs","lineNumber":47,"sourceCode":"        public StrokeCollection()\n        {\n        }\n\n        /// <summary>Creates a StrokeCollection based on a collection of existing strokes</summary>\n        public StrokeCollection(IEnumerable<Stroke> strokes)\n        {\n            ArgumentNullException.ThrowIfNull(strokes);\n\n            List<Stroke> items = (List<Stroke>)this.Items;\n\n            //unfortunately we have to check for dupes with this ctor\n            foreach ( Stroke stroke in strokes )\n            {\n                if ( items.Contains(stroke) )\n                {\n                    //clear and throw\n                    items.Clear();\n                    throw new ArgumentException(SR.StrokeIsDuplicated, nameof(strokes));\n                }\n                items.Add(stroke);\n            }\n        }\n\n        /// <summary>Creates a collection from ISF data in the specified stream</summary>\n        /// <param name=\"stream\">Stream of ISF data</param>\n        public StrokeCollection(Stream stream)\n        {\n            ArgumentNullException.ThrowIfNull(stream);\n            if ( !stream.CanRead )\n            {\n                throw new ArgumentException(SR.Image_StreamRead, nameof(stream));\n            }\n\n            Stream seekableStream = GetSeekableStream(stream);\n            if (seekableStream == null)\n            {","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Ink/StrokeCollection.cs#L29-L65","documentation":"The StrokeCollection(IEnumerable<Stroke> strokes) constructor copies the input while checking for duplicates; if the same Stroke instance appears twice, it clears the partially built collection and throws ArgumentException(SR.StrokeIsDuplicated) naming the strokes parameter. Stroke instances must be unique within a collection.","triggerScenarios":"Calling new StrokeCollection(strokes) where strokes contains the same Stroke reference twice, e.g. a list built by adding an already-present stroke, or union of two overlapping selections without deduplication.","commonSituations":"Merging selections from multiple strokes' hit tests; concatenating StrokeCollections and passing the result to the constructor; Distinct() omitted from LINQ pipelines.","solutions":["De-duplicate the input before constructing: new StrokeCollection(input.Distinct())","Build via AddRange on an existing StrokeCollection and handle duplicates yourself","Check for duplicates manually (items.Contains) before constructing"],"exampleFix":"// before\nvar sc = new StrokeCollection(selectedStrokes);\n// after\nvar sc = new StrokeCollection(selectedStrokes.Distinct());","handlingStrategy":"validation","validationCode":"bool hasDuplicates = strokes is not null && strokes.GroupBy(s => s).Any(g => g.Count() > 1);","typeGuard":"static bool AreDistinct(IEnumerable<Stroke>? list) => list is not null && list.Distinct().Count() == list.Count();","tryCatchPattern":"try { var sc = new StrokeCollection(strokes); } catch (ArgumentException ex) when (ex.Message.Contains(\"duplicate\")) { var sc = new StrokeCollection(strokes.Distinct()); }","preventionTips":["Apply .Distinct() before constructing StrokeCollection","Avoid adding the same Stroke instance to a collection twice","Track selected strokes in a HashSet<Stroke>"],"tags":["wpf","ink","duplicate","collection"],"backgroundTag":"invalid-argument-value","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}