c# - 为什么 Python.NET 使用基方法而不是派生类中的方法?

标签 c# python .net oop python.net

编辑:这将在新版本的 pythonnet 中得到修复(当 this 合并请求时)。

我对 Python.NET 继承有疑问。我有一个包含以下代码的 DLL:

using System;

namespace InheritanceTest
{
    public class BaseClass
    {
        public bool Transmit()
        {
            throw new NotImplementedException();
        }
    }

    public class InheritedClass: BaseClass
    {
        public new bool Transmit()
        {
            Console.WriteLine("Success!");
            return true;
        }
    }
}

我希望调用 InheritedClass 实例的 Transmit 方法写入控制台并返回 true 和 Transmit 方法BaseClass 抛出 NotImplementedException。

当运行以下 python 代码时:

## setup
import clr
import os

clr.AddReference(os.getcwd() + '\\InheritanceTest.dll')
import InheritanceTest

## method test

base_class = InheritanceTest.BaseClass()
base_class.Transmit() # throws a NotImplementedException as expected

inherited_class = InheritanceTest.InheritedClass()
inherited_class.Transmit() # still throws a NotImplementedException, although it should call InheritedClass.Transmit

我使用的是 pythonnet 2.3.0 版和 .NET Framework 4.6.1。感谢您的帮助!

编辑:this question 没有回答这个问题.那里,据说

The new modifier instructs the compiler to use your child class implementation instead of the parent class implementation. Any code that is not referencing your class but the parent class will use the parent class implementation.

这显然不是这里发生的事情。

编辑 2:这似乎是 pythonnet 库的问题。 The issue is now on github.

最佳答案

pythonnet 方法解析(methodbinder.cs 文件中的Bind 方法)可以改进很多恕我直言。不管怎样,这个方法目前并不真正关心类型层次结构。

一个简单的解决方案是更改 MethodSorter 类,使其在对方法进行排序以确定 Bind 调用将选择哪个方法时优先派生类。

之前:

internal class MethodSorter : IComparer
{
    int IComparer.Compare(object m1, object m2)
    {
        int p1 = MethodBinder.GetPrecedence((MethodBase)m1);
        int p2 = MethodBinder.GetPrecedence((MethodBase)m2);
        if (p1 < p2)
        {
            return -1;
        }
        if (p1 > p2)
        {
            return 1;
        }
        return 0;
    }
}

之后:

internal class MethodSorter : IComparer
{
    int IComparer.Compare(object m1, object m2)
    {
        var me1 = (MethodBase)m1;
        var me2 = (MethodBase)m2;
        if (me1.DeclaringType != me2.DeclaringType)
        {
            // m2's type derives from m1's type, favor m2
            if (me1.DeclaringType.IsAssignableFrom(me2.DeclaringType))
                return 1;

            // m1's type derives from m2's type, favor m1
            if (me2.DeclaringType.IsAssignableFrom(me1.DeclaringType))
                return -1;
        }

        int p1 = MethodBinder.GetPrecedence((MethodBase)m1);
        int p2 = MethodBinder.GetPrecedence((MethodBase)m2);
        if (p1 < p2)
        {
            return -1;
        }
        if (p1 > p2)
        {
            return 1;
        }
        return 0;
    }
}

请注意,我没有进行过广泛的测试,所以我不确定这是否会破坏其他东西。正如我所说,整个方法绑定(bind)代码看起来很脆弱。

关于c# - 为什么 Python.NET 使用基方法而不是派生类中的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52868552/

相关文章:

.net - 方法什么时候可以被 CLR 内联?

c# - 用于替换除数字之外的所有字符的正则表达式

用于 C++ 对象销毁的 C# 一次性模式

python - 切换 Homebrew 安装的 Python 版本

python - 合并多个csv文件与python中不同列的错误与writerow

c# - ADAL 身份验证错误 Multi-Tenancy

c# - 什么方式比较好 : make own wrapper for DbContext or use DbContext in Controller

python - Django项目文件结构

c# - 具有多个参数的 Shutdown.exe 进程,不工作

c# - 寻找需要多个接口(interface)继承(而不是实现)的示例/案例