Repository: AvaloniaUI/Avalonia
File: src/Avalonia.Input/DragDropDevice.cs (C#)

Code before:
﻿using Avalonia.Interactivity;
using Avalonia.VisualTree;
using System.Linq;
using Avalonia.Input.Raw;

namespace Avalonia.Input
{
    public class DragDropDevice : IDragDropDevice
    {
        public static readonly DragDropDevice Instance = new DragDropDevice();
        
        private Interactive _lastTarget = null;
        
        private Interactive GetTarget(IInputElement root, Point local)
        {
            var target = root.InputHitTest(local)?.GetSelfAndVisualAncestors()?.OfType<Interactive>()?.FirstOrDefault();
            if (target != null && DragDrop.GetAllowDrop(target))
                return target;
            return null;
        }
        
        private DragDropEffects RaiseDragEvent(Interactive target, IInputElement inputRoot, Point point, RoutedEvent<DragEventArgs> routedEvent, DragDropEffects operation, IDataObject data)
        {
            if (target == null)
                return DragDropEffects.None;
            var args = new DragEventArgs(routedEvent, data, target, target != null ? inputRoot.TranslatePoint(point, target) : point)
            {
                RoutedEvent = routedEvent,
                DragEffects = operation
            };
            target.RaiseEvent(args);
            return args.DragEffects;
        }
        
        private DragDropEffects DragEnter(IInputElement inputRoot, Point point, IDataObject data, DragDropEffects effects)
        {
            _lastTarget = GetTarget(inputRoot, point);
            return RaiseDragEvent(_lastTarget, inputRoot, point, DragDrop.DragEnterEvent, effects, data);
        }

        private DragDropEffects DragOver(IInputElement inputRoot, Point point, IDataObject data, DragDropEffects effects)
        {
            var target = GetTarget(inputRoot, point);

            if (target == _lastTarget)
                return RaiseDragEvent(target, inputRoot, point, DragDrop.DragOverEvent, effects, data);
            
            try
            {
                if (_lastTarget != null)
                    _lastTarget.RaiseEvent(new RoutedEventArgs(DragDrop.DragLeaveEvent));

Review comment (suggestion):
If `target` is never null, then it should probably be checked as an invariant on entering this method, e.g.

```
Contract.Requires<ArgumentNullException>(target != null);
```

Doing the check here suggests it can sometimes be null.

Code after:
﻿using Avalonia.Interactivity;
using Avalonia.VisualTree;
using System.Linq;
using Avalonia.Input.Raw;

namespace Avalonia.Input
{
    public class DragDropDevice : IDragDropDevice
    {
        public static readonly DragDropDevice Instance = new DragDropDevice();
        
        private Interactive _lastTarget = null;
        
        private Interactive GetTarget(IInputElement root, Point local)
        {
            var target = root.InputHitTest(local)?.GetSelfAndVisualAncestors()?.OfType<Interactive>()?.FirstOrDefault();
            if (target != null && DragDrop.GetAllowDrop(target))
                return target;
            return null;
        }
        
        private DragDropEffects RaiseDragEvent(Interactive target, IInputElement inputRoot, Point point, RoutedEvent<DragEventArgs> routedEvent, DragDropEffects operation, IDataObject data)
        {
            if (target == null)
                return DragDropEffects.None;
            var args = new DragEventArgs(routedEvent, data, target, inputRoot.TranslatePoint(point, target))
            {
                RoutedEvent = routedEvent,
                DragEffects = operation
            };
            target.RaiseEvent(args);
            return args.DragEffects;
        }
        
        private DragDropEffects DragEnter(IInputElement inputRoot, Point point, IDataObject data, DragDropEffects effects)
        {
            _lastTarget = GetTarget(inputRoot, point);
            return RaiseDragEvent(_lastTarget, inputRoot, point, DragDrop.DragEnterEvent, effects, data);
        }

        private DragDropEffects DragOver(IInputElement inputRoot, Point point, IDataObject data, DragDropEffects effects)
        {
            var target = GetTarget(inputRoot, point);

            if (target == _lastTarget)
                return RaiseDragEvent(target, inputRoot, point, DragDrop.DragOverEvent, effects, data);
            
            try
            {
                if (_lastTarget != null)
                    _lastTarget.RaiseEvent(new RoutedEventArgs(DragDrop.DragLeaveEvent));