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
NullReferenceException
on this.This particular api feature is about convenience and intuition and while the
NullReferenceException
approach 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.Value
to aref Object
parameter throwsArgumentException: Missing parameter does not have a default value
. And I can’t see how we would support default values forref
parameters 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.Invoke
tries it’s best to give you a usable result back. That’s why you getSystem.Reflection.Pointer
back 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
,object
orMissing
-I am dereferencing when I demand a value form a ref returning method. And dereferencing
null
throws. I do not see why calling via reflection should behave any differently.It is not uncommon to handle all the stuff in terms of
object
s 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.Value
flowing around would be hard.The case is not very different from when I give you a
null
array and ask for a first element or give anull
instance 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
TypeReference
based 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
.