Proposal: Params everything #6490
Replies: 17 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. |
Beta Was this translation helpful? Give feedback.
-
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? |
Beta Was this translation helpful? Give feedback.
-
[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?
|
Beta Was this translation helpful? Give feedback.
-
Also, please fix your compiler translation. It should be: var param = new Foo { bar2 = 12 };
MyMethod(param); Note bar2 instead of bar. |
Beta Was this translation helpful? Give feedback.
-
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. |
Beta Was this translation helpful? Give feedback.
-
@HaloFour That's cool! Can I see what it looks like? |
Beta Was this translation helpful? Give feedback.
-
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. |
Beta Was this translation helpful? Give feedback.
-
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. |
Beta Was this translation helpful? Give feedback.
-
If you agree on restricting param types to structs (first point of @jnm2), then you cannot use inheritance (answer to my third question) 😉 |
Beta Was this translation helpful? Give feedback.
-
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. |
Beta Was this translation helpful? Give feedback.
-
I think it would need a different syntax to be unambiguous. Say MyMethod(12 to bar2); |
Beta Was this translation helpful? Give feedback.
-
@bondsbw Sure you can't use a .To extension method for that? 😂 |
Beta Was this translation helpful? Give feedback.
-
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 |
Beta Was this translation helpful? Give feedback.
-
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" } }); |
Beta Was this translation helpful? Give feedback.
-
I agree with @HaloFour, it took me quite a while to realize that |
Beta Was this translation helpful? Give feedback.
-
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 |
Beta Was this translation helpful? Give feedback.
-
Converting to a discussion. This should be considered as part of #179. |
Beta Was this translation helpful? Give feedback.
-
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 ;)
Beta Was this translation helpful? Give feedback.
All reactions