Skip to content

About

Experimental Roslyn implementation of a proposed C# argument-forwarding syntax (`...`) for forwarding enclosing function parameters into method invocations while preserving standard C# type checking and overload resolution.

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Proposal discussion: argument forwarding expression using ...

Summary

I would like to discuss a C# argument forwarding expression using ... inside invocation argument lists.

The goal is to make forwarding methods, local functions, and lambdas easier to write and safer to maintain by allowing the current callable’s parameters to be forwarded into another invocation.

static void Forward(int x, string y)
{
    Target(...);
}

static void Target(int x, string y)
{
}

The intent is that Target(...) behaves as though the parameters of Forward were written explicitly:

Target(x, y);

Motivation

Forwarding methods are common in wrapper APIs, overload funnels, logging/decorator layers, adapter methods, local functions, and lambdas.

Today, forwarding requires manually repeating every parameter:

static void Forward(
    int id,
    string name,
    CancellationToken cancellationToken)
{
    Target(id, name, cancellationToken);
}

This repetition is easy to get wrong when parameters are added, removed, reordered, or changed to ref, out, or in.

An argument forwarding expression would let the developer express intent directly:

static void Forward(
    int id,
    string name,
    CancellationToken cancellationToken)
{
    Target(...);
}

Proposed behavior

For an initial version, ... would only be valid inside a normal invocation argument list.

Target(...);
Target(prefix, ...);
Target(..., suffix);

When used, ... expands to the parameters of the containing callable in declaration order.

static void Forward(int x, string y)
{
    Target(0, ...);
}

would behave like:

Target(0, x, y);

The forwarded arguments should participate in normal overload resolution and type inference.

Ref kind behavior

The forwarding expression should preserve parameter passing mode.

static void Forward(ref int x, out string y, in DateTime z)
{
    Target(...);
}

static void Target(ref int x, out string y, in DateTime z)
{
}

This should behave like:

Target(ref x, out y, in z);

Invalid cases

For a conservative first version, these should be invalid:

Target(x: ...);      // named forwarding
Target(ref ...);     // explicit ref on forwarding expression
new C(...);          // object creation
Target(..., ...);    // multiple forwarding expressions in same argument list

Open design questions

  1. Should ... forward all containing parameters, or only “remaining” parameters based on position?
  2. Should explicit arguments after ... be allowed?
  3. Should ... be allowed in constructors or object creation?
  4. Should multiple ... expressions be disallowed, as proposed here?
  5. Is ... the right syntax?
  6. Should this feature support attributes, indexers, delegates, or function pointer invocations, or only ordinary method invocations?
  7. Should lambda/local-function forwarding be allowed?

Prototype

I have a local Roslyn prototype that implements this experimentally.

The prototype includes:

  • DotDotDotToken
  • ForwardArgumentsExpressionSyntax
  • parser support for ... inside argument lists
  • binder expansion before overload resolution
  • preservation of ref, out, and in
  • diagnostics for invalid contexts
  • tests for:
    • lexing/parsing
    • basic forwarding
    • overload resolution
    • generic type inference
    • optional parameters
    • params
    • ref, out, and in
    • local functions and lambdas
    • invalid contexts
    • duplicate forwarding

I am not submitting the implementation as a PR yet because I understand substantial language features should be discussed first. I would like feedback on whether this direction is worth pursuing, whether the syntax/semantics are appropriate, and what design constraints should be considered before any implementation PR.


Microsoft Repositories:

This code branch is branched from the Roslyn main branch on 08/15/2026

This is where the discussion is located for the language feature: dotnet/csharplang#10308


Files Updated:

M src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs M src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs M src/Compilers/CSharp/Portable/CSharpResources.resx M src/Compilers/CSharp/Portable/Errors/ErrorCode.cs M src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs M src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 M src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs M src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs M src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs M src/Compilers/CSharp/Portable/Parser/LanguageParser.cs M src/Compilers/CSharp/Portable/Parser/Lexer.cs M src/Compilers/CSharp/Portable/Syntax/Syntax.xml M src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs M src/Compilers/CSharp/Portable/Syntax/SyntaxKindFacts.cs M src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf M src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf M src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf M src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf M src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf M src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf M src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf M src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf M src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf M src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf M src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf M src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf M src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf M src/Compilers/CSharp/Test/Emit2/CodeGen/CodeGenCallTests.cs M src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs M src/Compilers/CSharp/Test/Syntax/LexicalAndXml/LexicalTests.cs M src/Compilers/CSharp/Test/Syntax/Parsing/ExpressionParsingTests.cs

About

Experimental Roslyn implementation of a proposed C# argument-forwarding syntax (`...`) for forwarding enclosing function parameters into method invocations while preserving standard C# type checking and overload resolution.

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages