IDisposable & iterator disposal
Void.IDisposable is part of the root library contract. Collection enumerators and compiler-generated iterators can dispose deterministically, including pending iterator cleanup.
VOID Language lifetime & abstractions
VOID now combines IDisposable, iterator and foreach disposal, using statements/declarations, generic method inference, extension methods, static interface contracts, constrained static calls, and default interface methods without adding a second lifetime or dispatch system.
Completed lifetime & abstraction foundation
Disposal lowers through the same structured cleanup model built for exceptions and finally. Generic inference and extension methods reuse normal overload resolution. Static/default interface methods extend the existing interface model rather than introducing a parallel runtime representation.
IDisposable & iterator disposalVoid.IDisposable is part of the root library contract. Collection enumerators and compiler-generated iterators can dispose deterministically, including pending iterator cleanup.
Non-array foreach disposes its enumerator on normal completion, early break, return, and exception paths through structured cleanup.
C#-style using (...) works with disposable reference and value types, null resources, nesting, exceptions, and normal GC behavior.
using var and typed using declarations dispose resources at scope exit in reverse declaration order across normal and exceptional exits.
Generic calls can omit explicit type arguments when VOID can infer them through the existing overload resolver and monomorphizer, including constrained and by-reference cases where inference is well-defined.
Static methods with a this first parameter can participate in instance-style call syntax while preserving ordinary instance-member precedence and normal overload resolution.
Interfaces can require static methods as compile-time contracts, implemented by ordinary public static methods on concrete classes or structs without interface-owned static storage.
Generic code constrained by an interface can call required static members through the type parameter; monomorphization lowers the call to the concrete static implementation.
Interface methods may provide bodies. Concrete implementations take precedence, inherited defaults provide fallback behavior, and ambiguous inherited defaults are diagnosed.
One cleanup model
using builds on finally, not beside it.VOID already had structured exits, rethrow, GC-safe unwinding, and iterator cleanup. Deterministic disposal extends that control-flow foundation, so resource cleanup stays predictable instead of becoming another compiler-only special case.
public sealed class GameFile : IDisposable
{
public void Dispose()
{
Console.WriteLine("closed");
}
}
using (GameFile file = new GameFile())
{
Run(file);
}public static T Identity<T>(T value)
{
return value;
}
public static int Twice(this int value)
{
return value * 2;
}
int value = Identity(21);
Console.WriteLine(value.Twice() == 42);public interface IFactory<T>
{
static T Create();
string Name()
{
return "default";
}
}
public static T Build<T, TFactory>()
where TFactory : IFactory<T>
{
return TFactory.Create();
}Iterator lifetime
Pattern locals and managed intermediate values that survive yield are promoted into normal iterator state-machine storage, remain rooted through suspension and forced GC, and participate in disposal, exception, finally, and teardown cleanup without a parallel capture system.