runtime: Existing reflection APIs should be able to invoke ref-returning methods and return a value
Related to: https://github.com/dotnet/roslyn/issues/8489
The scenario seems to be explicitly forbidden. Possibly due to ref returning methods not being common in the past.
Note that this issue does not ask for a new API that would allow returning a ref.
This is just about the existing APIs that returns the result as an object. It seems that they should work with ref returning methods by evaluating the target, reading the value indirectly and returning the value as object.
object result1 = inst.RefReturningMethod();
// should be the same as
object result2 = inst.GetType().InvokeMember(inst, . . ., "RefReturningMethod",. . .);
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 2
- Comments: 36 (25 by maintainers)
Commits related to this issue
- Enable Invoke and GetValue for ref-returning members (#17639) * Enable Invoke and GetValue for ref-returning members https://github.com/dotnet/corefx/issues/15960 Returned magic object is the o... — committed to dotnet/coreclr by deleted user 6 years ago
- Add tests for Invoke of ref-returning members (#29305) * Add tests for Invoke of ref-returning members https://github.com/dotnet/corefx/issues/15960 * Added ActiveIssue for Project N — committed to dotnet/corefx by deleted user 6 years ago
Thanks everyone for the spirited debate.
I’m going to have to side with team
NullReferenceExceptionon this.This particular api feature is about convenience and intuition and while the
NullReferenceExceptionapproach makes the ref case a bit more “special” (*), it mirrors exactly the way that refs make early bound calls special. I don’t think it would be confusing. It also has the advantage of not adding new surface area or punning existing ones.The TypeReferenced-based api will be the one that’s functionally complete and has consistent behavior for all types.
(*) It’s already special by virtue of the fact that we’re bundling an indirection and providing no access to the ref itself.
I think we could swing that. Today, passing
Missing.Valueto aref Objectparameter throwsArgumentException: Missing parameter does not have a default value. And I can’t see how we would support default values forrefparameters so there isn’t a chance for a conflict. Or we could invent a new sentinal value if necessary.That concern would be solvable by adding a new sentinel value for this.
This would execute the target method (successfully) and then throw - it’s a behavior that doesn’t have a precedent for this API. I would want to run this through API review.
MethodInfo.Invoke is not equivalent to
object result = RefReturningMethod();.MethodInfo.Invoketries it’s best to give you a usable result back. That’s why you getSystem.Reflection.Pointerback for methods that return unmanaged pointers (instead of just throwing and telling you to go away because you can’t box pointer types). It’s a special value that is not what the boxed result of invocation was, but something that lets you reconstruct it.I thought about this a bit more and I firmly think that NRE is the right choice here.
and if the method returns
nullptr, I do get NRE (in both C# and VB and I assume in any other language). Regardless of the actual type of the method. -int,objectorMissing-I am dereferencing when I demand a value form a ref returning method. And dereferencing
nullthrows. I do not see why calling via reflection should behave any differently.It is not uncommon to handle all the stuff in terms of
objects when doing something dynamic. I might never need to unbox the value or unbox it far away from the call. In either case figuring when and what went wrong and why I have a boxedMissing.Valueflowing around would be hard.The case is not very different from when I give you a
nullarray and ask for a first element or give anullinstance and ask for a field. Would you find it more logical to throw something or return aMissing.Value? Would people think the exception is because of a reflection bug?The more general
TypeReferencebased API might be able to work withnullptr, since we would be dealing with references. Even then I am not very sure. Probably.For the value based API the behavior seems clear - the user is asking to obtain a value of a ref-returning method. That implies dereferencing and possible NRE if the method returns
nullptr.