Runtime: Microsoft.CSharp should allow operations on identically-named types

Created on 11 Nov 2017  Â·  6Comments  Â·  Source: dotnet/runtime

In the rare case that two types have exactly the same type name, dynamic operations will fail:

C# dynamic x = Activator.CreateInstance( AssemblyBuilder .DefineDynamicAssembly(new AssemblyName("TestAssembly"), AssemblyBuilderAccess.Run) .DefineDynamicModule("TestModule") .DefineType("TestType", TypeAttributes.Public) .CreateType()); dynamic y = Activator.CreateInstance( AssemblyBuilder .DefineDynamicAssembly(new AssemblyName("TestAssembly"), AssemblyBuilderAccess.Run) .DefineDynamicModule("TestModule") .DefineType("TestType", TypeAttributes.Public) .CreateType()); x.Equals(y); // This or any other operation with both objects fails.

dotnet/corefx#23021 changed the exception thrown in this case from RuntimeBinderInternalCompilerException to RuntimeBinderException; pretty much a change from "sorry, we got this wrong" to "sorry, you can't do that".

Ideally such cases should succeed. While the case is extremely rare:

  1. It's always better to allow users to do something that prohibit.
  2. By the very nature of dynamic binding, there's no theoretical justification for disallowing it.
  3. Handling the exception requires resetting a lot of state. Allowing this reset means a lot of objects being passed around so that the type manager, symbol manager, etc. can be accessed by those objects that need them, tying those objects to each other, in order to deal with this rare case.

While the first two points relate to what is an obscure edge case, the third is a greater motivation for allowing this IMO.

CC: @VSadov @OmarTawfik

area-Microsoft.CSharp

Most helpful comment

Thanks a lot @JonHanna with your explanation it's much more clear. In fact my debugger was always breaking on this ResetBindException, so I thought it was a real issue, but you are right: it is handled internally and then the evaluation works. I guess working too late is never a good idea: you then find issues which aren't.

@karelz thanks for the time to answer me.

All 6 comments

@JonHanna Is there a way to workaround the issue in a 4.6.2 project?
Maybe I can install Microsoft.Csharp from nuget?

@molinch maybe work from nightlies? I know less about the various packaging versions than I really should, so someone else would give a better answer (@karelz ?)
The best I can think of is to use explicit reflection instead of dynamic.

Basically in my case I am using Roslyn scripting API, and provide some dynamic into the globals object passed to scripting API.
c# public class FormulaGlobals { public dynamic g; }
I have a couple of scripts, and they assign different values to g (which is in fact a Dictionary). My scripts then access it this way g["SOMETHING"]
But at some point I get this ResetBindException. I'm pretty sure your commit would fix it.

I guess there is no way to clear the DLR cache?

@molinch. You should never see the ResetBindException as it should never escape MS.CSharp. Generally it should, as the name suggests, reset its global state and try again and only if it happens again in the second attempt — which would mean there were two different but identically-named types in the same operation — it should throw RuntimeBinderInternalCompilerException (or for a brief period with .NET Core, RuntimeBinderException). If ResetBindException is escaping into the calling code there's something else wrong.

Packaging is sill a bit of black magic for me as well :( (way too complicated with too many exceptions)

In general / high-level, we do not release standalone NuGet packages for all CoreFX-produced packages for all platforms -- Microsoft.CSharp seems to be in that category (from looking at its latest nuget package).
If there is a workaround, use it. If it is critical bug without reasonable workaround affecting non-trivial number of applications/customers, we may consider alternatives ...

Thanks a lot @JonHanna with your explanation it's much more clear. In fact my debugger was always breaking on this ResetBindException, so I thought it was a real issue, but you are right: it is handled internally and then the evaluation works. I guess working too late is never a good idea: you then find issues which aren't.

@karelz thanks for the time to answer me.

Was this page helpful?
0 / 5 - 0 ratings