gpt4 book ai didi

c# - 使用反射确定 C# 方法是否具有关键字 'override'

转载 作者:行者123 更新时间:2023-11-30 16:30:23 25 4
gpt4 key购买 nike

我原以为可以轻松找到这个问题的答案,但我没有。我想知道是否有可能确定一个方法是否具有关键字“override”归因于它,给定它的 MethodInfo 实例。

我在想也许以下方法可以实现这一点:

/// <summary> Returns whether the specified methodInfo is attributed with the keyword 'override'. </summary>
public static bool IsOverriding(this MethodInfo methodInfo)
{
if (methodInfo == null) throw new ArgumentNullException();
return methodInfo.DeclaringType != methodInfo.GetBaseDefinition().DeclaringType;
}

我已经成功地测试了一些非虚拟的、虚拟的和抽象的例子,但我觉得我遗漏了一些场景,可能是隐藏或泛型(尽管我不知道这将如何发挥作用)。

最佳答案

我也试图找到这个东西。从问题中,你给出了得到 IsOverriding 的想法为 override 工作关键词。但是为了隐藏,我尝试创建 IsHiding关键字 new .这是基本的 C# OOP:

  • override仅在基于方法包含 abstract 时使用或 virtual修饰语。
  • new用于隐藏具有相同名称的基于方法但是...
  • new不能应用于 abstract基方法,因为它会产生编译器错误。
  • 然而有趣的部分是new如果基本方法包含 virtual,也可以应用于方法.

插入部分是我们可以隐藏或覆盖 virtual方法。我们知道 GetBaseDefinition()将返回基地 MethodInfo如果我们override一个virtual方法。但区分它的关键是 GetBaseDefinition()将返回相同的 MethodInfo而不是基础 MethodInfo如果我们隐藏virtual方法。

override关键字是必须的 new仅用于抑制警告消息。所以我们可以区分overridenew通过 IsAbstractIsVirtual结合DeclaringTypeBaseType .

    public static bool IsOverriding(this MethodInfo methodInfo)
{
if (methodInfo == null) throw new ArgumentNullException("methodInfo");
return methodInfo.DeclaringType != methodInfo.GetBaseDefinition().DeclaringType;
}

public static bool IsHiding(this MethodInfo methodInfo)
{
if (methodInfo == null) throw new ArgumentNullException("methodInfo");
if (methodInfo.DeclaringType == methodInfo.GetBaseDefinition().DeclaringType)
{
var baseType = methodInfo.DeclaringType.BaseType;
if (baseType != null)
{
MethodInfo hiddenBaseMethodInfo = null;
var methods = baseType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Static);
foreach (var mi in methods)
if (mi.Name == methodInfo.Name)
{
var miParams = mi.GetParameters();
var methodInfoParams = methodInfo.GetParameters();
if (miParams.Length == methodInfoParams.Length)
{
var i = 0;
for (; i < miParams.Length; i++)
{
if (miParams[i].ParameterType != methodInfoParams[i].ParameterType
|| ((miParams[i].Attributes ^ methodInfoParams[i].Attributes).HasFlag(ParameterAttributes.Out))) break;

// Simplified from:
//if (miParams[i].ParameterType != methodInfoParams[i].ParameterType
// || (miParams[i].Attributes.HasFlag(ParameterAttributes.Out) && !methodInfoParams[i].Attributes.HasFlag(ParameterAttributes.Out))
// || !(miParams[i].Attributes.HasFlag(ParameterAttributes.Out) && methodInfoParams[i].Attributes.HasFlag(ParameterAttributes.Out))) break;
}
if (i == miParams.Length)
{
hiddenBaseMethodInfo = mi;
break;
}
}
}
if (hiddenBaseMethodInfo != null && !hiddenBaseMethodInfo.IsPrivate) return true;
}
}
return false;
}

我使用简单的继承对其进行了测试并且它有效。我不考虑泛型方法..还..


编辑:我只是更改了上面的代码,因为我忘记了关于继承类型可以包含新声明的方法的想法,这些方法不应该被威胁为新的。 IsHiding()将首先确保它具有相同的 DeclaringType (它看起来像新的)但需要通过 DeclaringType.BaseType 查看基本声明类型如果存在同名方法。

注意因为没有BindingFlags.DeclaredOnly , GetMethod()将搜索整个基本类型,因此无需递归搜索每个基本类型。 BindingFlags.FlattenHierarchy用于在抽象-抽象基类中包含静态方法,如下所示:

public abstract class A
{
public static void Stat() { }
}
public abstract class B : A
{
}
public class C: B
{
public new static void Stat() { }
}

编辑:我只是修复了 IsHiding()上面检查基本方法重载并防止AmbiguousMatchException通过使用 GetMethods()而不是 GetMethod() .经测试可与不同参数结合使用的过载,与 ref 混合使用, out , params和可选参数。根据参数计数、参数类型及其修饰符比较重载的签名:

  • refout包含在签名中,但两者不能相互重载。
  • 返回类型,可选(默认值)和params右边的大部分参数应该被忽略

refParameterType 相比本身(在调试过程中查看结尾的“&”)并且不需要通过 IsByRef 进行比较而 outAttributes 相比旗帜。当且仅当其中一个属性具有标志 Out 时,我使用简化表达式按位 XOR 来跳过循环这使得签名不同。不要与 HasFlag 混淆在 .NET 4 中,它只是想确保 Out异或结果bit为1。

关于c# - 使用反射确定 C# 方法是否具有关键字 'override',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5746447/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com