{"record":{"id":"b14acb8f8da43e65","repo":"dotnet/wpf","slug":"throw-new-ambiguousmatchexception","errorCode":null,"errorMessage":"throw new AmbiguousMatchException();","messagePattern":"throw new AmbiguousMatchException\\(\\);","errorType":"exception","errorClass":"AmbiguousMatchException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/ComponentModel/AttachedPropertyMethodSelector.cs","lineNumber":33,"sourceCode":"    ///     matching to find a match for any parameters that are\n    ///     compatible.\n    /// </summary>\n    internal class AttachedPropertyMethodSelector : Binder \n    {\n        /// <summary>\n        ///     The only method we implement.  Our goal here is to find a method that best matches the arguments passed.\n        ///     We are doing this only with the intent of pulling attached property metadata off of the method.\n        ///     If there are ambiguous methods, we simply take the first one as all \"Get\" methods for an attached\n        ///     property should have identical metadata.\n        /// </summary>\n        public override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers)\n        {\n            // Short circuit for cases where someone didn't pass in a types array.\n            if (types == null) \n            {\n                if (match.Length > 1) \n                {\n                    throw new AmbiguousMatchException();\n                }\n                else\n                {\n                    return match[0];\n                }\n            }\n\n            for(int idx = 0; idx < match.Length; idx++)\n            {\n                MethodBase candidate = match[idx];\n                ParameterInfo[] parameters = candidate.GetParameters();\n                if (ParametersMatch(parameters, types)) \n                {\n                    return candidate;\n                }\n            }\n\n            return null;","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/ComponentModel/AttachedPropertyMethodSelector.cs#L15-L51","documentation":"AttachedPropertyMethodSelector.SelectMethod (a Binder override used by WPF's attached-property method resolution) throws AmbiguousMatchException when no types array is supplied and more than one candidate MethodInfo matches. Without type information it cannot disambiguate between overloads.","triggerScenarios":"Resolving an attached property getter/setter method where multiple overloads match the method name and the caller passed types == null to SelectMethod.","commonSituations":"XAML/attached-property processing selecting methods like GetFoo/SetFoo that have overloads; reflection-based property engine lookups without explicit parameter types.","solutions":["Provide a types array so overload resolution can disambiguate the candidates","Rename or remove the duplicate overloads so only one method matches the attached-property naming convention","Ensure attached property accessor signatures follow the exact expected pattern (single DependencyObject parameter for getters)","Catch AmbiguousMatchException at the resolution site and apply a tie-breaking rule"],"exampleFix":"// before\nbinder.SelectMethod(bindingAttr, match, null, modifiers);\n// after\nbinder.SelectMethod(bindingAttr, match, new Type[] { typeof(DependencyObject) }, modifiers);","handlingStrategy":"validation","validationCode":"if (match == null) throw new ArgumentNullException(nameof(match));\nif (types == null && match.Length > 1)\n    throw new AmbiguousMatchException(\"Multiple overloads; provide types array\");","typeGuard":"bool UnambiguousWithoutTypes(MethodBase[] m) => m != null && (m.Length == 1 || m.Select(x => x.GetParameters().Length).Distinct().Count() == 1);","tryCatchPattern":"try { var mi = binder.SelectMethod(bindingAttr, match, types, modifiers); }\ncatch (AmbiguousMatchException) { mi = match.FirstOrDefault(x => x.GetParameters().Length == 1); }","preventionTips":["Always supply a types array when resolving possibly-overloaded methods","Follow the standard attached-property accessor signature (Get*/Set* with DependencyObject first param)","Avoid declaring multiple overloads for attached property accessors"],"tags":["wpf","reflection","binder","ambiguity"],"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-21T21:30:21.729Z"}