private bool SameArguments(
            FieldDefPair fieldDefPair1,
            FieldDefPair fieldDefPair2)
        {
            var arguments1 = fieldDefPair1.Field.Arguments?
                             .ToDictionary(l => l.Name, l => l);

            var arguments2 = fieldDefPair2.Field.Arguments?
                             .ToDictionary(l => l.Name, l => l);

            if (arguments1 == null && arguments2 == null)
            {
                return(true);
            }

            if (arguments1 == null)
            {
                return(false);
            }

            if (arguments2 == null)
            {
                return(false);
            }

            if (arguments1.Count() != arguments2.Count())
            {
                return(false);
            }

            return(arguments1.All(arg1 =>
            {
                if (!arguments2.ContainsKey(arg1.Key))
                {
                    return false;
                }

                var arg2 = arguments2[arg1.Key];

                var value1 = Arguments.CoerceArgumentValue(
                    _context.Schema,
                    _context.VariableValues,
                    arg1.Key,
                    fieldDefPair1.FieldDef.GetArgument(arg1.Key),
                    arg1.Value);

                var value2 = Arguments.CoerceArgumentValue(
                    _context.Schema,
                    _context.VariableValues,
                    arg1.Key,
                    fieldDefPair2.FieldDef.GetArgument(arg1.Key),
                    arg2);

                return SameValue(value1, value2);
            }));
        }
        private Conflict FindConflict(
            ValidationContext context,
            Dictionary <SelectionSet, CachedField> cachedFieldsAndFragmentNames,
            PairSet comparedFragmentPairs,
            bool parentFieldsAreMutuallyExclusive,
            string responseName,
            FieldDefPair fieldDefPair1,
            FieldDefPair fieldDefPair2)
        {
            var parentType1 = fieldDefPair1.ParentType;
            var node1       = fieldDefPair1.Field;
            var def1        = fieldDefPair1.FieldDef;

            var parentType2 = fieldDefPair2.ParentType;
            var node2       = fieldDefPair2.Field;
            var def2        = fieldDefPair2.FieldDef;

            // If it is known that two fields could not possibly apply at the same
            // time, due to the parent types, then it is safe to permit them to diverge
            // in aliased field or arguments used as they will not present any ambiguity
            // by differing.
            // It is known that two parent types could never overlap if they are
            // different Object types. Interface or Union types might overlap - if not
            // in the current state of the schema, then perhaps in some future version,
            // thus may not safely diverge.

            var areMutuallyExclusive =
                parentFieldsAreMutuallyExclusive ||
                parentType1 != parentType2 && isObjectType(parentType1) && isObjectType(parentType2);

            // return type for each field.
            var type1 = def1?.ResolvedType;
            var type2 = def2?.ResolvedType;

            if (!areMutuallyExclusive)
            {
                // Two aliases must refer to the same field.
                var name1 = node1.GetName();
                var name2 = node2.GetName();

                if (name1 != name2)
                {
                    return(new Conflict
                    {
                        Reason = new ConflictReason
                        {
                            Name = responseName,
                            Message = new Message
                            {
                                Msg = $"{name1} and {name2} are different fields"
                            }
                        },
                        FieldsLeft = new List <ISelection> {
                            node1
                        },
                        FieldsRight = new List <ISelection> {
                            node2
                        }
                    });
                }

                // Two field calls must have the same arguments.
                if (!SameArguments(node1.GetArguments(), node2.GetArguments()))
                {
                    return(new Conflict
                    {
                        Reason = new ConflictReason
                        {
                            Name = responseName,
                            Message = new Message
                            {
                                Msg = "they have differing arguments"
                            }
                        },
                        FieldsLeft = new List <ISelection> {
                            node1
                        },
                        FieldsRight = new List <ISelection> {
                            node2
                        }
                    });
                }
            }

            if (type1 != null && type2 != null && DoTypesConflict(type1, type2))
            {
                return(new Conflict
                {
                    Reason = new ConflictReason
                    {
                        Name = responseName,
                        Message = new Message
                        {
                            Msg = $"they return conflicting types {type1} and {type2}"
                        }
                    },
                    FieldsLeft = new List <ISelection> {
                        node1
                    },
                    FieldsRight = new List <ISelection> {
                        node2
                    }
                });
            }

            // Collect and compare sub-fields. Use the same "visited fragment names" list
            // for both collections so fields in a fragment reference are never
            // compared to themselves.
            var selectionSet1 = node1.GetSelectionSet();
            var selectionSet2 = node2.GetSelectionSet();

            if (selectionSet1 != null && selectionSet2 != null)
            {
                var conflicts = FindConflictsBetweenSubSelectionSets(
                    context,
                    cachedFieldsAndFragmentNames,
                    comparedFragmentPairs,
                    areMutuallyExclusive,
                    type1.GetNamedType(),
                    selectionSet1,
                    type2.GetNamedType(),
                    selectionSet2);

                return(SubfieldConflicts(conflicts, responseName, node1, node2));
            }

            return(null);
        }