Improved overload inference from generic type parameters/constraints #741
Replies: 11 comments
-
This sounds very similar to #478. There's also dotnet/roslyn#15166, which was closed by the author as covered by Shapes/Type classes (#110). |
Beta Was this translation helpful? Give feedback.
-
This statement has really taken me by surprise. Could you, @markrendle (or anyone else), point me to any reference materials that explains this? My understanding of structs and interfaces was that any reference to a struct via an interface resulted in boxing. I need to know more, please! 😲 |
Beta Was this translation helpful? Give feedback.
-
If you know the struct type, then you know the non-virtual struct methods (public or private) which implement the interface and don't have to do a virtual call and you can pass the reference to the struct. |
Beta Was this translation helpful? Give feedback.
-
@DavidArno the jit always emits a specialized implementation for any struct instantiation. As it's a struct (and can't have any subtypes, or virtual calls) then all calls through the interface constraints on it just become direct calls to the struct members.
The trick here is that you don't have a "Reference to a struct via an interface". You always just have the struct. It's just that the struct has a constraint. Constraints are not references to the interface. They're just a contract about what the value must be implementing. |
Beta Was this translation helpful? Give feedback.
-
This has clearly uncovered a serious hole in my knowledge around interfaces and structs. I have to confess I'm not sure I really understand what either of you are saying. But I appreciate you taking the trouble to reply and you have given me info to start searching and experimenting with. I feel I've probably hijacked Mark's topic enough now though, so many thanks for your replies. 👍 |
Beta Was this translation helpful? Give feedback.
-
Even if you do this to avoid boxing the struct when getting access to the IEnumerable implementation, you still end up probably boxing the enumerator (or allocating one) when the accessing code calls IEnumerable.GetEnumerator(). |
Beta Was this translation helpful? Give feedback.
-
Yeah, he needs |
Beta Was this translation helpful? Give feedback.
-
@mattwar I was using the IEnumerable as an example. My actual use case involves using a struct carrying a delegate and state to avoid closure allocations, but I'm sure there are lots of places where this optimization would be useful but make the code look clunky with all the explicit generic parameters. |
Beta Was this translation helpful? Give feedback.
-
Link to the issue that inspired this one At present, calling an public TResult Execute<T1, TResult>(Func<T1, TResult> func, T1 arg1)
{
var pollyAction = PollyAction.Create(func, arg1); // returns a PollyAction struct instance
return Execute<PollyAction<T1, TResult>, TResult>(action); // explicit type parameters required
}
private TResult Execute<TAction, TResult>(TAction action)
where TAction : struct, IPollyAction<TResult>
{
try
{
return action.Execute();
}
catch { ... }
} |
Beta Was this translation helpful? Give feedback.
-
@kingces95 Mentioning myself so this shows up in my filter instead of having to jump around from the similar issue I opened dotnet/roslyn#18867. |
Beta Was this translation helpful? Give feedback.
-
@agocke is investigating extending type inference to take constraints into account. |
Beta Was this translation helpful? Give feedback.
-
I'm sure I've seen this somewhere but I can't find it.
If I have an struct
Foo
that implementsIEnumerable<T>
, then I can define a generic method like so:Now I can pass my struct without the overhead of the boxing allocation to the interface, but C#'s overload resolution can't infer the type parameters, so I have to explicitly specify them:
It should be possible to infer those type parameters from the type of
Foo
and the constraint onTEnumerable
.Is there an open issue covering this, or did I dream it?
Beta Was this translation helpful? Give feedback.
All reactions