-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Proposal]: Params Collections (VS 17.10, .NET 9) #7700
Comments
Great proposal. It would be great if we could include ranges at the call site via ..list notation. |
Something I would love for this proposal to consider too is unmanaged implements. (especially important with game engines like Unity for interop, and e.g. Burst requires it). Specifically implementing a // Library code
ref struct SystemState {}
interface ISystem {
public void Update<multi T>(ref SystemState state, params Span<T> values) where T : IComponent {}
}
// User Code
struct MyGameSystem : ISystem {
// This part has to be able to be fully unmanaged
public void Update(ref SystemState state, ComponentA a, ComponentB b, ComponentC c){}
}
// Managed code can call it like:
ComponentA a = default;
ComponentB b = default;
ComponentC c = default;
ISystem mySystem = new MyGameSystem();
mySystem.Update(ref state, stackalloc IComponent[]{ a, b, c }); // managed and upon resolve checks length == 3
// Unmanaged code can of course only do
ComponentA a = default; // unmanaged struct
ComponentB b = default; // unmanaged struct
ComponentC c = default; // unmanaged struct
MyGameSystem mySystem = new MyGameSystem();
mySystem.Update(ref state, a, b, c );
// note: in Unity most cases will have reflection finding the bursted/native function pointers that actually calls the specified methods from an unmanaged context. Today we are sadly forced to fake multiple type params. Examples for projects I work on: |
I think that would fall under variadic type parameters: dotnet/roslyn#5058 I don't understand how your example would work. The contract stipulates that you can pass 0..x parameters of any |
@Daxode |
It should also be possible to follow a public Task<int> FooAsync(params int[] values, CancellationToken ct) |
I like the proposal, makes the language feel more natural and complete in my opinion |
|
I could see supporting that via optional parameters, in that they must be named at the callsite. Otherwise, that sounds like that would make overload resolution infinitely more complicated. var fooResult = FooAsync(10, 20, 40, base: 6, something: "something", ct: ct); With collection expressions, it also feels unnecessary since you could wrap the params in brackets: var fooResult = FooAsync([10, 20, 40], 6, "something", ct); |
Somewhat unrelated, but it would be cool if I could require at least one value when using params. In a way that created an error at compile-time. Perhaps with an attribute? |
@wolffaayyy Yup. An attribute + analyzer would be an easy thing to add (and can be done today) :) |
Yes, the is proposal is better than to simply extend the support for e.g. |
This is a great proposal that will make the caller code more readable and flexible as well as the parameter in the method more flexible and readable. I am personally all for it. |
This is possible even with C#12, all it needs is square brackets surrounding the params parameter during invocation. //string DisplayActionSheet(string title, params string[] buttons) {} - classic definition
string DisplayActionSheet(string title, IEnumerable<string> buttons) {}
// Invocation
var result = DisplayActionSheet("Unsaved Changes?", ["Save", "Discard", "Cancel"]); |
@egvijayanand That's the idea. We want to unify so that you can write either the collection form, or the params form, with the same semantics. Thsi greatly simplifies the language and unifies the concepts between these two areas. It also helps given an intuition in terms of how things should behave (both for users and us) since we want these to all be consistent. |
I will take it like this. Once implemented, params parameter is going to take any type that implements |
@egvijayanand Not quite. Rather: Once implemented, you can use The distinction here is subtle, but very relevant though. As an example |
Wow, collection expressions are getting further updates in C# 13. |
The unification would be really cool if you could take the void L(params List<string> args) {}
L([foo, ..bar]); // works
L(foo, ..bar); // but what about this?
// maybe non-linear support could be added some day?
void D(params IEnumerable<KeyValuePair<string, object>> kwargs) {}
D(["foo": 12, ..bar]); // will work
D("foo": 12, ..bar); // this would be cool
D(foo: 12, ..bar); // this would be super-cool |
Considering params has to be last (I believe) I could see this being feasible, but I don't think they'll do this. As I understood it, params collection is mostly a performance (in combination with overload resolution priority & existing params arrays overloads with params ROS) and consistency kind of thing. If params arrays didn't exist, then params collections wouldn't be worked on, as collection expressions are just better |
I'm really looking forward to this. It would also be nice if I could use .. in the params section. |
This is an ambitious proposal, but I would even be satistied with the simpler original scope of #1757 I'd love to see allocation-free |
This proposal is already implemented in the compiler |
@mstefarov thta proposal was subsumed into this one. Which is already being done for c#13 and which the runtime is already utilizing for their APIs. |
@MovGP0 - What happens if I want to pass in a |
I don't see the use case. Usually you would create a combined CancellationTokenSource and return a single CancellationToken. But that is a synchronous operation. |
The point isn't the use case. public Task<int> FooAsync(params CancellationToken[] values, CancellationToken ct)``` |
Yes, that would be possible. It's just a collection that is passed to the method. So the syntax is fine. It's just that it doesn't make sense to have a |
How about default values? public Task<int> FooAsync(params CancellationToken[] values, CancellationToken? ct = null) |
Implicit conversion from strings to |
Can someone help to answer the following question about the design of this proposal?
Given a struct with a reference type (e.g. StrctWithRefMember), will params span of the following method (ParamsMethod) allocate on stack or heap when called from the method Main()?
|
What is about DllImport? If you use
Does it work? I will install net 9.0 on Linux Mint. |
Params Collections
Summary
In C# 12 language added support for creating instances of collection types beyond just arrays.
See collection expressions.
This proposal extends
params
support to all such collection types.This is a placeholder issue for this proposal: https://github.com/dotnet/csharplang/blob/main/proposals/params-collections.md
The proposal subsumes earlier proposals for params spans (#1757) and params IEnumerables (#179).
Design meetings
The text was updated successfully, but these errors were encountered: