Repository: pythonnet/pythonnet (language: python)

Issue:
Generic virtual method in baseclass causes InvalidProgramException
### Environment

-   Pythonnet version: 3.0.0-preview2022-04-11
-   Python version: 3.10
-   Operating System: MacOS and Ubuntu 2021.4
-   .NET Runtime: .net 6

### Details

If I create a python class which inherits from a C# class that has a virtual generic method and exception is thrown while the class is being defined. Note, not during object instanciation time.

To reproduce, take the following C# class:
```cs
    public abstract class GenericVirtualMethodTest
    {
        public virtual Q VirtMethod<Q>(Q arg1)
        {
            return arg1;
        }
    }
```

Then inherit from it as in this test:

```py
def test_virtual_generic_method():
    class OverloadingSubclass(GenericVirtualMethodTest):
        __namespace__ = "test_virtual_generic_method_cls"
    obj = OverloadingSubclass()
    assert obj.VirtMethod[int](5) == 5
```

The result is the following exception (Actually a C# exception inside a python exception inside a C# exception):
```
Python.Runtime.PythonException : An attempt was made to load a program with an incorrect format.
 (0x8007000B)
  File "/Users/bruger/code/work/pythonnet/src/../tests/test_subclass.py", line 268, in test_virtual_generic_method
    class OverloadingSubclass(GenericVirtualMethodTest):
  File "<string>", line 19, in <module>
   at Python.Runtime.PythonException.ThrowLastAsClrException() in /Users/bruger/code/work/pythonnet/src/runtime/PythonException.cs:line 53
   at Python.Runtime.PythonException.ThrowIfIsNull(NewReference& ob) in /Users/bruger/code/work/pythonnet/src/runtime/PythonException.cs:line 455
   at Python.Runtime.PythonEngine.RunString(String code, BorrowedReference globals, BorrowedReference locals, RunFlagType flag) in /Users/bruger/code/work/pythonnet/src/runtime/PythonEngine.cs:line 625
   at Python.Runtime.PythonEngine.Exec(String code, PyDict globals, PyObject locals) in /Users/bruger/code/work/pythonnet/src/runtime/PythonEngine.cs:line 530
   at Python.PythonTestsRunner.PythonTestRunner.RunPythonTest(String testFile, String testName) in /Users/bruger/code/work/pythonnet/src/python_tests_runner/PythonTestRunner.cs:line 64
-----

One or more child tests had errors
  Exception doesn't have a stacktrace
```

### Proposed Fix

I understand that it is probably a bit complicated to actually override a virtual generic method in python code and maybe it is not even necesary. So maybe the best solution is to just ignore virtual methods in this case.





Discussion / hints:

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 13bf09c2c..2347895a8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,8 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
 
 ### Fixed
 
+- Fixed error occuring when inheriting a class containing a virtual generic method.
+
 ## [3.0.1](https://github.com/pythonnet/pythonnet/releases/tag/v3.0.1) - 2022-11-03
 
 ### Added
diff --git a/src/runtime/Types/ClassDerived.cs b/src/runtime/Types/ClassDerived.cs
index cf6d9b16b..61c602783 100644
--- a/src/runtime/Types/ClassDerived.cs
+++ b/src/runtime/Types/ClassDerived.cs
@@ -220,7 +220,10 @@ internal static Type CreateDerivedType(string name,
             foreach (MethodInfo method in methods)
             {
                 if (!method.Attributes.HasFlag(MethodAttributes.Virtual) |
-                    method.Attributes.HasFlag(MethodAttributes.Final))
+                    method.Attributes.HasFlag(MethodAttributes.Final)
+                    // overriding generic virtual methods is not supported
+                    // so a call to that should be deferred to the base class method.
+                    || method.IsGenericMethod)
                 {
                     continue;
                 }


Test patch:
diff --git a/src/testing/generictest.cs b/src/testing/generictest.cs
index 238435811..b333910c2 100644
--- a/src/testing/generictest.cs
+++ b/src/testing/generictest.cs
@@ -136,4 +136,12 @@ public static T[] EchoRange<T>(T[] items)
             return items;
         }
     }
+
+    public abstract class GenericVirtualMethodTest
+    {
+        public virtual Q VirtMethod<Q>(Q arg1)
+        {
+            return arg1;
+        }
+    }
 }
diff --git a/tests/test_subclass.py b/tests/test_subclass.py
index a51e89da3..504b82548 100644
--- a/tests/test_subclass.py
+++ b/tests/test_subclass.py
@@ -9,7 +9,7 @@
 import System
 import pytest
 from Python.Test import (IInterfaceTest, SubClassTest, EventArgsTest,
-                         FunctionsTest, IGenericInterface)
+                         FunctionsTest, IGenericInterface, GenericVirtualMethodTest)
 from System.Collections.Generic import List
 
 
@@ -327,3 +327,15 @@ def test_generic_interface():
     obj = GenericInterfaceImpl()
     SpecificInterfaceUser(obj, Int32(0))
     GenericInterfaceUser[Int32](obj, Int32(0))
+
+def test_virtual_generic_method():
+    class OverloadingSubclass(GenericVirtualMethodTest):
+        __namespace__ = "test_virtual_generic_method_cls"
+    class OverloadingSubclass2(OverloadingSubclass):
+        __namespace__ = "test_virtual_generic_method_cls"
+    obj = OverloadingSubclass()
+    assert obj.VirtMethod[int](5) == 5
+    obj = OverloadingSubclass2()
+    assert obj.VirtMethod[int](5) == 5
+
+