Voiced call of a general method with explicit typical type behavior

I have a non-generic class with a generic method. The generic type of this method determines the type of inference and cannot be deprecated, so I have to explicitly provide a generic type. Sometimes this type is passed from the general type parameter of the caller's method, but in one case I have to explicitly provide it myself.

The problem is that when I call my explicitly provided generic type method call it seems like it fails and returns a completely unnecessary type. I cannot debug this call and get invalid results. But this does not violate the execution, which is especially strange. When the same method is called from a different location where the generic type is passed from the generic call method type, everything seems to work as defined.

I completely lost what was happening.

Defining my method in the interface (and implemented later in the class):

TRecord Update<TRecord>(int recordId, int? categoryId, string categoryName, string title)
    where TRecord : Record;

      

My Record

class is not abstract and there is only one type that inherits from it:

public class Record : ProtectedEntity
{
    ...
}

public class RelatedRecord<T> : Record
{
    public IList<T> Related { get; private set; }
    ...
}

      

I am calling my method:

var record = myRepo.Update<Record>(...);

      

When execution moves to that line, I hit F11to debug, but execution just moves to the next sentence. When I check my variable Record

, it is not a type Record

, but rather System.String

a parameter value categoryName

. This means that something is being executed, but this is definitely not the body of my general method.

The strange thing is that everywhere the same call works as expected.

How can this be explained and what am I doing wrong?

+3


source to share


2 answers


From what you say, including the comment:

If I try to access any of the members at runtime, it of course throws an exception due to non-existent members.

it sounds like a compiler error or JIT error. This means that in order to diagnose it, we need more knowledge about the compiler you are using (the exact version) and / or the JIT you are using. In the event of a compiler error, it may be enough if you can just show the IL that was generated if you are familiar with it.

Note that the latest VS preview includes a completely new JIT (RyuJIT) and enables it by default on a system-wide scale, so if you installed VS preview that would be my guess. If so, you can trivially disable it to check.


Note that the other option is something like an alias using

, for which the aliases Record

must be System.String

or the aliases var

are equal System.String

(plus some implicit conversion operators, etc.). This is unlikely, but I've seen it happen: p

Edit: the above is excluded by your comment:



Doing typeof (Write) .FullName correctly returns my fully qualified type name including namespaces, as it should.

So we are left with a compiler error or JIT error.


If it is a RyuJIT bug, here are the options to disable it (I use the config first, since it's the easiest):

  • As environment variable: set COMPLUS_useLegacyJit = 1

  • In the registry: Install HKLM or HKCU, Software \ Microsoft.NETFramework. Key name: useLegacyJit. Type: REG_DWORD. Value: 1

  • In the app.exe.config file:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <runtime>
        <useLegacyJit enabled="1" />
      </runtime>
    </configuration>
    
          

(this comes from a separate discussion with MS I had earlier)

+2


source


If you are not getting a runtime type exception, then I may suspect a bug in the Visual Studio debugger that I am facing. If you have two locally bounded variables with the same name in the same method, the debugger can confuse them:

private void DoSomething(int x)
{
    {
        var s = "STRING!";
        Console.WriteLine(s);
    }
    {
        var s = 5;
        Console.WriteLine(s);
    }
}

      



I don't know if the above example will actually reproduce the issue, but I've seen debugger behavior where you hover over the second s and it shows it as "STRING!" And not 5. That would be the first thing I wanted would check that you don't have another local variable in the same method as "write".

+1


source







All Articles