I have a non-generic class with a generic method. Generic type on this method defines output type and can't be inferred from usage so I have to explicitly provide generic type. Sometimes this type is passed on from generic caller's method type parameter, but in one instance I have to explicitly provide it myself.
The problem is when I call my explicitly provided generic type method call it seems that it doesn't get executed and returns a completely irrelevant type. I can't debug into this call and get invalid results. But it doesn't break execution which is especially strange. When the same method is called from elsewhere where generic type is passed on from caller's generic method type, everything seems to work as per definition.
I'm completely lost what's going on.
My method definition in the interface (and is implemented later in the class):
TRecord Update<TRecord>(int recordId, int? categoryId, string categoryName, string title)
where TRecord : Record;
My Record
class is non-abstract and and there's only one type that inherits from it:
public class Record : ProtectedEntity
{
...
}
public class RelatedRecord<T> : Record
{
public IList<T> Related { get; private set; }
...
}
I'm calling my method doing this:
var record = myRepo.Update<Record>(...);
When execution gets to this line I hit F11 to debug into it, but execution just jumps to the next sentence. When I check my record
variable it's not of type Record
but rather System.String
, having the value of parameter categoryName
. This means that something does get executed but it's definitely not the body of my generic method.
The strange thing is that everywhere else the same call works as expected.
How can this be explained and what am I doing wrong?
From what you are saying, including the comment:
If I try to access any members during runtime it of course throws an exception about non existing members.
it sounds like either a compiler bug or JIT bug. That means to diagnose it we need more knowledge of the compiler you are using (exact version) and/or the JIT you are using. In the case of a compiler bug, it may suffice if you can simply show the IL that has been generated, if you're familiar with that.
Note that the most recent VS preview includes an entirely new JIT (RyuJIT) and enables it by default system-wide, so if you have installed the VS preview, that would be my guess. If so, you can disable it trivially to check.
Note the other option here is something like a using
alias that aliases Record
to be System.String
, or aliases var
to be System.String
(plus some implicit conversion operators, etc). These are unlikely, but I've seen it happen ;p
Edit: the above is ruled out by your comment:
doing typeof(Record).FullName correctly returns my full type name including namespaces as it should.
So we are left with compiler bug or JIT bug.
If this is a RyuJIT bug, here are the options to disable it (I suggest using the config one first, as it is the easiest to do):
As an environment variable: set COMPLUS_useLegacyJit=1
In the registry: Set HKLM or HKCU, Software\Microsoft.NETFramework. Key name: useLegacyJit. Type: REG_DWORD. Value: 1
In an app.exe.config file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<useLegacyJit enabled="1" />
</runtime>
</configuration>
(these come from a separate discussion with MS that I had previously)