Coplt.Dropping

July 8, 2026 ยท View on GitHub

Nuget MIT

Auto gen dispose pattern

  • Auto handle Dispose(bool dispoing) pattern
  • Auto handle destructor/finalizer
  • Allow multiple drops
  • Specify the drop order [Drop(Order = X)]
  • The first argument of Drop target method can be bool disposing
  • Mark Drop directly on fields and properties (requires target type have Dispose method)
  • Dose not supported AsyncDispose, too complicated, it is recommended to implement it manually
  • Drop can mark on static methods, will pass this on first argument, if have bool disposing will be the second argument

Example

  • Basic usage

    [Dropping]
    public partial class Foo1
    {
        [Drop]
        public void Drop()
        {
            Console.WriteLine(1);
        }
    }
    

    Generate output:

    Foo1.dropping.g.cs
    // <auto-generated/>
    
    #nullable enable
    
    using Coplt.Dropping;
    
    public partial class Foo1 : global::System.IDisposable
    {
    
        protected virtual void Dispose(bool disposing)
        {
            Drop();
        }
    
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        ~Foo1()
        {
            Dispose(false);
        }
    
    }
    

  • Drop Froms

    [Dropping(From = DropFrom.Dispose)]
    public partial class Foo2
    {
        [Drop]
        public void Drop()
        {
            Console.WriteLine(1);
        }
    }
    
    [Dropping(From = DropFrom.Finalizer)]
    public partial class Foo3
    {
        [Drop]
        public void Drop()
        {
            Console.WriteLine(1);
        }
    }
    

    Generate output:

    Foo2.dropping.g.cs
    // <auto-generated/>
    
    #nullable enable
    
    using Coplt.Dropping;
    
    public partial class Foo2 : global::System.IDisposable
    {
    
        protected virtual void Dispose(bool disposing)
        {
            if (disposing) Drop();
        }
    
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        ~Foo2()
        {
            Dispose(false);
        }
    
    }
    

    Foo3.dropping.g.cs
    // <auto-generated/>
    
    #nullable enable
    
    using Coplt.Dropping;
    
    public partial class Foo3 : global::System.IDisposable
    {
    
        protected virtual void Dispose(bool disposing)
        {
            if (!disposing) Drop();
        }
    
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        ~Foo3()
        {
            Dispose(false);
        }
    
    }
    

  • Inherit

    [Dropping]
    public partial class Foo8 : Foo1
    {
        [Drop]
        public void Drop1()
        {
            Console.WriteLine(1);
        }
    }
    

    Generate output:

    Foo8.dropping.g.cs
    // <auto-generated/>
    
    #nullable enable
    
    using Coplt.Dropping;
    
    public partial class Foo8 : global::System.IDisposable
    {
    
        protected override void Dispose(bool disposing)
        {
            Drop1();
            base.Dispose(disposing);
        }
    
    }
    

  • Sealed And Struct

    [Dropping]
    public partial struct Foo7
    {
        [Drop]
        private void Drop()
        {
            Console.WriteLine(1);
        }
    }
    
    [Dropping]
    public sealed partial class Foo9
    {
        [Drop]
        private void Drop()
        {
            Console.WriteLine(1);
        }
    }
    
    [Dropping(From = DropFrom.Dispose)]
    public sealed partial class Foo10
    {
        [Drop]
        private void Drop()
        {
            Console.WriteLine(1);
        }
    }
    
    [Dropping(From = DropFrom.Finalizer)]
    public sealed partial class Foo11
    {
        [Drop]
        private void Drop()
        {
            Console.WriteLine(1);
        }
    }
    

    Generate output:

    Foo7.dropping.g.cs
    // <auto-generated/>
    
    #nullable enable
    
    using Coplt.Dropping;
    
    public partial struct Foo7 : global::System.IDisposable
    {
    
        public void Dispose()
        {
            Drop();
        }
    
    }
    
    Foo9.dropping.g.cs
    // <auto-generated/>
    
    #nullable enable
    
    using Coplt.Dropping;
    
    public partial class Foo9 : global::System.IDisposable
    {
    
        public void Dispose()
        {
            Drop();
            GC.SuppressFinalize(this);
        }
    
        ~Foo9()
        {
            Dispose();
        }
    
    }
    
    Foo10.dropping.g.cs
    // <auto-generated/>
    
    #nullable enable
    
    using Coplt.Dropping;
    
    public partial class Foo10 : global::System.IDisposable
    {
    
        public void Dispose()
        {
            Drop();
        }
    
    }
    
    Foo11.dropping.g.cs
    // <auto-generated/>
    
    #nullable enable
    
    using Coplt.Dropping;
    
    public partial class Foo11 : global::System.IDisposable
    {
    
        private void Dispose(bool disposing)
        {
            if (!disposing) Drop();
        }
    
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        ~Foo11()
        {
            Dispose(false);
        }
    
    }
    

More see Tests