Skip to content

[API Proposal]: Introduce a MoveAttribute parameter attribute for explicit ownership transfer #132198

Description

@metaone01

Background and motivation

I previously opened a discussion in the csharplang repo (dotnet/csharplang#9909) regarding a move parameter modifier. The idea is to explicitly transfer an object's ownership into a function, after which the original variable should be considered invalid – similar to std::move() in C++.

A community member suggested that this proposal might be better aligned with the runtime repo, potentially as a new attribute in the System namespace.

I would like to propose adding an attribute like [Move] – that allows explicit ownership transfer for object parameters. This would make object lifetime semantics more transparent and help prevent use‑after‑move errors.

One typical scenario involves database commands that must be submitted to a transaction or require custom preprocessing before execution. Once a command object is passed to another function (e.g., a transaction commit handler), it should never be modified afterwards – any inadvertent change could corrupt the operation.

The proposed feature aims to make the transfer of data and the invalidation of the original variable an indivisible logical step. This eliminates the need for developers to manually set the variable to null after passing it, which is error‑prone and often forgotten. More importantly, it provides compile‑time enforcement, catching bugs that could otherwise arise from:

  • Code reordering (e.g., accidental use after the logical transfer).
  • Unintentional modifications in collaborative development.
  • Simple oversight when refactoring or extending code.

By clearly marking the point of ownership transfer, the language would enforce correct usage and reduce the mental burden on developers, especially in large codebases where object lifetime is critical.

Related Discussions
dotnet/csharplang#9909
dotnet/csharplang#6612

API Proposal

namespace System.Runtime.CompilerServices
{
    public sealed class MoveAttribute : Attribute
    {
        public MoveAttribute() { }
    }
}

API Usage

1     public class Item : IDisposable { ... }
2
3     public void TakeOwnership([Move] Item item)   // or void TakeOwnership(move Item item)
4     {
5         item.Dispose();
6     }
7     
8     public void Creator()
9     {
10        Item item = new();
11        TakeOwnership(item);   // or TakeOwnership(move item);
12        bool use = item.A; // Error: ownership already transferred at line 11 (TakeOwnership(item);)
13    }

Alternative Designs

No response

Risks

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions