如何在.net中获取类型的定义运算符

Posted

技术标签:

【中文标题】如何在.net中获取类型的定义运算符【英文标题】:How to get defined operators for a type in .net 【发布时间】:2022-01-20 17:33:16 【问题描述】:

我正在尝试获取特定类型的已定义运算符列表,以查看可以将哪种操作应用于该类型。

例如,Guid 类型支持 ==!= 操作。

因此,如果用户想要对 Guid 类型应用 操作,我可以在异常发生之前处理这种情况。

或者,如果我有运算符列表,我可以强制用户只使用列表中的操作。

在对象浏览器中可以看到运算符,因此可能有一种方法可以通过反射访问它们,但我找不到那种方法。

任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

使用Type.GetMethods 获取方法,然后使用MethodInfo.IsSpecialName 发现运算符、转换等。这是一个示例:

using System;
using System.Reflection;

public class Foo

    public static Foo operator +(Foo x, Foo y)
    
        return new Foo();
    
    
    public static implicit operator string(Foo x)
    
        return "";
    


public class Example 

    
    public static void Main()
    
        foreach (MethodInfo method in typeof(Foo).GetMethods(BindingFlags.Static | BindingFlags.Public))
        
            if (method.IsSpecialName && method.Name.StartsWith("op_"))
            
                Console.WriteLine(method.Name);
            
        
    

【讨论】:

嗨,感谢您的快速回复!我认为这适用于大多数类型,但是当我尝试 Int32 时,它返回一个空集。有什么建议吗? 是的,原始类型的运算符就是这样“有趣”的。我怀疑您基本上必须对它们的列表进行硬编码。不要忘记原语不包括decimalDateTimeTimeSpan or Guid`。 为了完整起见,Nullable<T> 上的“提升”运算符也可以称为“有趣”;-p 你不想过滤if (method.IsSpecialName) && method.Name.StartsWith("op_"))否则你也会得到属性getter和setter @Charlieface:你当然可以,是的。不知道是不是特别需要……【参考方案2】:

C# 4.0 具有动态语言运行时特性,那么使用dynamic 类型怎么样?

using Microsoft.CSharp.RuntimeBinder;

namespace ListOperatorsTest

class Program

    public static void ListOperators(object inst)
    
        dynamic d = inst;

        try
        
            var eq = d == d; // Yes, IntelliSense gives a warning here.
            // Despite this code looks weird, it will do
            // what it's supposed to do :-)
            Console.WriteLine("Type 0 supports ==", inst.GetType().Name);

        
        catch (RuntimeBinderException)
        
        

        try
        
            var eq = d <= d;
            Console.WriteLine("Type 0 supports <=", inst.GetType().Name);

        
        catch (RuntimeBinderException)
        
        

        try
        
            var eq = d < d;
            Console.WriteLine("Type 0 supports <", inst.GetType().Name);

        
        catch (RuntimeBinderException)
        
        

        try
        
            var add = d + d;
            Console.WriteLine("Type 0 supports +", inst.GetType().Name);
        
        catch (RuntimeBinderException)
        
        

        try
        
            var sub = d - d;
            Console.WriteLine("Type 0 supports -", inst.GetType().Name);
        
        catch (RuntimeBinderException)
        
        

        try
        
            var mul = d * d;
            Console.WriteLine("Type 0 supports *", inst.GetType().Name);
        
        catch (RuntimeBinderException)
        
        

        try
        
            try
            
                var div = d / d;
            
            catch (DivideByZeroException)
            
            
            Console.WriteLine("Type 0 supports /", inst.GetType().Name);
        
        catch (RuntimeBinderException)
        
        
    

    private struct DummyStruct
    
    

    static void Main(string[] args)
    
        ListOperators(0);
        ListOperators(0.0);
        DummyStruct ds;
        ListOperators(ds);
        ListOperators(new Guid());
    


【讨论】:

以上是关于如何在.net中获取类型的定义运算符的主要内容,如果未能解决你的问题,请参考以下文章

.NET Core/EF Core 2.0 升级后急切加载“类型之间未定义强制运算符”

Flutter:没有为“Object”类型定义运算符“[]”。尝试定义运算符'[]'

如何在MATLAB中获取变量的类型

如何修复 SQLSTATE [42704]:未定义对象:7 错误:数据类型 json 在heroku 托管中没有访问方法“btree”的默认运算符类

未为“对象”类型定义运算符“[]”[重复]

如何定义自定义跨平台 size_t 类型?