-
Notifications
You must be signed in to change notification settings - Fork 1k
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
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 everything #1333
Comments
This is a fairly interesting idea that could make make scenarios like DI easier. dotnet/roslyn#16745, dotnet/efcore#7465 (comment) I'd think you'd want to restrict it to structs. That way there's always a default constructor, you don't force a heap allocation, the perf is the same as if you had passed each parameter individually, you don't have to worry about null reference exceptions, and it forces composition instead of inheritance. Seems like you'd want a separate attribute type though. |
Also, I'd prefer to restrict it to fields; no properties. It's not like it would be legitimate to allow properties to disguise logic as simple parameter assignments, would it? |
[Params]
class MyList : IList<int> { ... }
void MyMethod(params MyList list) { ... }
MyMethod(1, 2, 3); //Is this allowed?
[Params]
public class Foo
{
public Bar bar { get; set; }
}
[Params]
public class Bar
{
public int? foobar { get; set; }
}
void MyMethod(params Foo foo) { ... }
MyMethod(foobar: 3) //Will this work?
|
Also, please fix your compiler translation. It should be: var param = new Foo { bar2 = 12 };
MyMethod(param); Note bar2 instead of bar. |
The keyword The DI angle might be interesting, but that seems like something very easily solved by the DI container itself. I'd been using an extension providing support for this in Ninject some 8 years ago. |
@HaloFour That's cool! Can I see what it looks like? |
It's been a while but I recall it working through writing an interface that exposed the dependencies as properties, and then taking a dependency on that interface. The extension would create an implementation of that interface. |
The idea is borrowed from javascript, where functions often take anonymous object with different options which works quite nicely. With this proposal, C# could have something like that but type safe. The main advantage of this is the ability to reuse parameter group multiple times (different overloads etc) and make it look like you are calling normal methods. Creating options class for each call is also fine, if more cumbersome (at least with lack of inferred Breaking naming guidelines already happens with tuples, so this doesn't seem like such a big issue. @Happypig375 All those questions are interesting ones. My first thoughts are:
@jnm2 Excellent points, I agree on both counts. |
If you agree on restricting param types to structs (first point of @jnm2), then you cannot use inheritance (answer to my third question) 😉 |
It is indeed very useful in JavaScript. But I do not see what this has to do with varargs. It would be incredible to have structural typing capabilities in C# but they shouldn't be tied to parameter lists. As you know from JavaScript, being able to return such an ad hoc object is equally important. |
I think it would need a different syntax to be unambiguous. Say MyMethod(12 to bar2); |
@bondsbw Sure you can't use a .To extension method for that? 😂 |
Am I wrong in thinking this is more or less a form of splatting? No matter what, I highly approve but would propose using a different keyword for this. It would also allow objects taking lone |
In a somewhat related feature, it looks like F# is planning on adding public void M(params Dictionary<string, string> args)
{
...
} And then call it like this: M(a: "one", b: "two", c: "three"); Which would be the equivalent of this, in current C#: M(new Dictionary<string, string> { { "a", "one" }, { "b", "two" }, { "c", "three" } }); |
I agree with @HaloFour, it took me quite a while to realize that |
In my opinion, this would be an exotic feature. I'd rather have dictionary literals for this. Target-typed void M<K, V>(Dictionary<K, V> map) {}
M(new() { {"a", "one"} }); // error as currently specified
M(["a": "one"]); // I'd expect this to compile I took a note to bring this up for discussion. I wonder if that would worth it, considering that "dictionary literals" is already a possibility (#414). PS: As @HaloFour said, you can use |
Converting to a discussion. This should be considered as part of #179. |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
Summary
Allow arbitrary object types to be marked as
params
in method declarations to allow optional parameter reuse.Motivation
In API's with multiple optional parameters, maintaining multiple method overloads that take the same optional parameters is a pain. Overriding those methods is even more pain.
Optional parameters don't allow for non constant default values and you often have to give different meaning to
default
values.Detailed design
When using params keyword, passing any class/struct that has
[ParamsAttribute]
should be allowed. Classes with[ParamsAttribute]
are instantiated with default constructor and their properties are filled with values passed to method as optional parameters.I.E.
Gets translated to
[ParamsAttribute]
is used to avoid ambiguities with existing and future uses forparams
keyword (IEnumerable<T>/ICollection<T>/Span<T>/IDictionary<string, object>
).structs
param could be useful for avoiding allocations combined within
modifier onparams
parameter.Params could be generic parameter to allow for uses unforseen by the author of proposal ;)
The text was updated successfully, but these errors were encountered: