You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法修改抽象类时,如何检查变量是否实现带自引用泛型的IUnaryNegationOperators?

问题核心原因

IUnaryNegationOperators<TOperand, TResult>是.NET 7+引入的静态抽象接口,这类接口的约束仅在编译时生效,无法通过运行时的is关键字进行类型检查,因此原代码中的判断逻辑永远不会触发。

解决方案

方案一:反射检查并调用一元负号操作符

静态抽象接口的实现要求类型必须定义public static TResult operator -(TOperand operand)方法,直接通过反射查找该方法,存在则调用执行,否则抛出异常:

using System.Numerics;
using System.Reflection;

public abstract class Foo
{
    public abstract TResult test<TOperand, TResult>(TOperand operand);
}

public class Bar : Foo
{
    public override TResult test<TOperand, TResult>(TOperand operand)
    {
        // 查找符合签名的一元负号操作符方法
        var negationMethod = typeof(TOperand).GetMethod(
            "op_UnaryNegation",
            BindingFlags.Public | BindingFlags.Static,
            new[] { typeof(TOperand) });

        // 校验方法返回值与TResult匹配
        if (negationMethod != null && negationMethod.ReturnType == typeof(TResult))
        {
            return (TResult)negationMethod.Invoke(null, new object[] { operand });
        }

        throw new InvalidOperationException("类型未实现有效的一元负号操作符");
    }
}

方案二:私有泛型方法+编译时约束+运行时接口检查

定义带编译时约束的私有方法处理符合要求的类型,在重写的test方法中通过反射检查类型是否实现目标接口,满足条件则调用私有方法:

using System.Numerics;
using System.Reflection;

public abstract class Foo
{
    public abstract TResult test<TOperand, TResult>(TOperand operand);
}

public class Bar : Foo
{
    public override TResult test<TOperand, TResult>(TOperand operand)
    {
        // 构造泛型接口类型并检查实现情况
        var targetInterface = typeof(IUnaryNegationOperators<,>).MakeGenericType(typeof(TOperand), typeof(TResult));
        if (targetInterface.IsAssignableFrom(typeof(TOperand)))
        {
            // 反射调用带约束的私有方法
            var handlerMethod = typeof(Bar).GetMethod(
                "HandleNegation",
                BindingFlags.NonPublic | BindingFlags.Instance)!;
            var genericHandler = handlerMethod.MakeGenericMethod(typeof(TOperand), typeof(TResult));
            return (TResult)genericHandler.Invoke(this, new object[] { operand });
        }

        throw new InvalidOperationException("类型未实现IUnaryNegationOperators接口");
    }

    private TResult HandleNegation<TOperand, TResult>(TOperand operand)
        where TOperand : IUnaryNegationOperators<TOperand, TResult>
    {
        return -operand;
    }
}

方案对比

  • 方案一:兼容性更强,无需依赖.NET 7+的静态接口运行时特性,只要类型定义了一元负号操作符即可生效,覆盖范围更广。
  • 方案二:严格贴合“实现IUnaryNegationOperators接口”的需求,利用编译时约束保证类型安全,性能略优于直接反射调用操作符,但仅支持.NET 7及以上版本。

内容的提问来源于stack exchange,提问作者Dalton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 06:23:14