0

I have asked a similar question before and this is more or less a follow up question. (C# Template Function: Cannot do non-virutal member lookup in 'T' because it is a type parameter)

I want to access a static abstract variable in a template function:

public static T AsType<T>(...) where T : ICode
{
    //...
    if(InterfaceCode != T.InterfaceCode) return null;
    if(SubtypeCode != T.SubtypeCode) return null;
    //...
}
        

with

public interface ICode
{
    public static abstract ushort SubtypeCode { get; }
    public static abstract ushort InterfaceCode { get; }
}

Whenever I try to run this code following exception is thrown:

'T.InterfaceCode' threw an exception of type 'System.BadImageFormatException'

I upgraded my project from .NET Core 3.1 to .NET 7 recently, because I wanted to use this "feature" (and it was a suggested solution to my last question)

Please let me know if you need more background information. Thanks for your help!

Reproduce-able example:

internal class Program
    {
        static void Main(string[] args)
        {
            AsType<Test>(1, 3);
        }
        public static T AsType<T>(ushort InterfaceCode, ushort SubtypeCode) where T : ICode
        {
            //...
            if (InterfaceCode != T.InterfaceCode) return default(T);
            if (SubtypeCode != T.SubtypeCode) return default(T);
            //...
            return default(T);
        }
        public interface ICode
        {
            public static abstract ushort SubtypeCode { get; }
            public static abstract ushort InterfaceCode { get; }
        }
        public class Item : ICode
        {
            public static ushort SubtypeCode { get; } = 1;
            public static ushort InterfaceCode { get; } = 2;
        }
        public class Test : Item
        {
            public static new ushort InterfaceCode { get; } = 1;
            public static new ushort SubtypeCode { get; } = 3;
        }
    }

NOTE: It does NOT throw this error. It it only displayed in the debug environment (VS2022) when displaying T.InterfaceCode.

MP9
  • 45
  • 5
  • Please can you provide a [mcve] so that we can reproduce the issue without guessing at the rest of your code? (Just enough to reproduce the problem - we don't need any of your real business code.) – Jon Skeet Jun 03 '23 at 07:08
  • @JonSkeet this should do, right? – MP9 Jun 03 '23 at 07:18
  • Well it would be slightly better if it were in a class declaration so we could *literally* just copy/paste/compile/run, but it's close enough. However, when I put that into a `Program` class in a .NET 7 console app, it doesn't produce the exception. Does *just that code* throw the exception for you? Can you confirm that your TargetFramework is just net7.0? – Jon Skeet Jun 03 '23 at 07:20
  • @JonSkeet when debugging (stepping through) and hovering over `T.InterfaceCode` it shows `'T.InterfaceCode' threw an exception of type 'System.BadImageFormatException'` and it doesn't seem to be working when inheriting the class Item either (`class Test : Item {}`...) – MP9 Jun 03 '23 at 07:24
  • 1
    What happens when you just run from the command line though, with just `dotnet run`? If this is *only* showing up when stepping through code in the debugger, that's important information. – Jon Skeet Jun 03 '23 at 07:27
  • - updated reproduce-able example to show what i mean – MP9 Jun 03 '23 at 07:27
  • Your updated code still doesn't throw any exception when I run it from the command line - and I don't know whether it does for you, either. – Jon Skeet Jun 03 '23 at 07:29
  • @JonSkeet it doesn't display any errors. Just noticed that it is working fine when Item inherits directly from ICode. I only tested it with inheriting the Item class. – MP9 Jun 03 '23 at 07:30
  • Okay, it sounds like this is *just* a debugger issue then. – Jon Skeet Jun 03 '23 at 07:38
  • @JonSkeet Not really. In the provided example is `InterfaceCode` 1 and `T.InterfaceCode` should also be 1. Why does this check fail? Is it because I dont inherit ICode directly? – MP9 Jun 03 '23 at 07:42
  • Well now you're asking about a completely different problem. You reported an exception, so I expected to see an exception. If you're now surprised at the value returned, you should say so - that's *nowhere* in the question. It's very frustrating trying to help someone when the ground keeps shifting. That's why it's always useful to provide a [mcve] - but one which *actually* reproduces the problem that your question describes. – Jon Skeet Jun 03 '23 at 08:24

1 Answers1

0

Ok, I identified the real problem and found a solution.

As shown in the reproduce-able example I tried to inherit the class Item onto Test and hide the base members. Of course this won't work because these members are not from ICode.

The error on my side was to think it was an error from .NET 7 just because the debugger showed an exception when hovering over T.InterfaceCode. Because of this exception when trying to display the value, I was unable to detect the mistake from above.

I was able to solve it with inheriting ICode onto every subclass of Item. (class Test : Item, ICode {...})

Anyways, thanks for your help!

MP9
  • 45
  • 5